多次出现带有单选按钮的渲染组件问题
Having issue rendering components with radio buttons multiple times
先了解一下背景,我正在做一份问卷并决定开始学习 React.js。问卷的每个步骤都包括一个问题和一个 yes/no 单选按钮组,以及导航按钮。这是 jsfiddle。问题组件非常简单,我在父组件中将 formData 和保存数据函数传递给它。
以及问题部分的代码
var Question = React.createClass({
getInitialState: function() {
return {
}
},
createMarkup: function(html) {
return {
__html: html
};
},
render: function() {
var subtitle = this.props.subtitle || '';
var name = this.props.name;
if (this.props.formData[name] === undefined) {
var answer_yes = null;
var answer_no = null;
} else {
answer_yes = this.props.formData[name] == "yes" ? true : null;
answer_no = this.props.formData[name] == "no" ? true : null;
}
console.log(answer_yes);
console.log(answer_no);
return (
<div className="container-question">
<label className="default" dangerouslySetInnerHTML={this.createMarkup(this.props.question)}></label>
<span className="alert subtitle" dangerouslySetInnerHTML={this.createMarkup(subtitle)}></span>
<div className="form-group form-group-radio">
<div className="row">
<div className="col-xs-4">
<input type="radio" id={name + "_yes"} name={name} value="yes" defaultChecked={answer_yes} onChange={this.props.saveData}/><label htmlFor="yes">Yes</label><br></br>
<input type="radio" id={name + "_no"} name={name} value="no" defaultChecked={answer_no} onChange={this.props.saveData}/><label htmlFor="no">No</label>
</div>
</div>
</div>
</div>
);
}
});
问题是,当您 select 您对第一个问题的回答并点击下一步时,第二个问题的无线电控制随之改变,当您先回答第二个问题时也会发生同样的事情。我将 defaultChecked 的布尔变量存储为渲染函数中的局部变量,并将它们记录在控制台中。
我犯了什么明显的错误吗?感谢您的帮助。
这是一个更新后的 jsfiddle:https://jsfiddle.net/69z2wepo/8365/
问题是您在 React 中使用了所谓的 'uncontrolled component'。有关详细信息,请参阅此页面:https://facebook.github.io/react/docs/forms.html
为您的场景更改为受控组件意味着使用 checked
而不是 defaultChecked
。 defaultChecked
适用于不受控制的组件,其中输入控件(在您的情况下为单选按钮)的值不受组件的 props
或 render
方法控制。 React 的真正设计目的是使用受控组件,其中 props
/state
/render
完全驱动 UI 显示的内容。
从使用 defaultChecked
更改为 checked
时,您会注意到的第一件事是您将无法再更改 UI 中的无线电状态。发生这种情况的原因是因为虽然您的应用程序状态在您的 saveData
函数中被更改,但您的组件没有被重新渲染。
有几种不同的方法来处理这个问题。更新后的 jsfiddle 正在 saveData
期间重新呈现您的应用程序。理想情况下,这应该以不同的方式考虑。 saveData
应该从父组件中移出并进入 FormDataStore
概念(参见 React Flux 架构,https://facebook.github.io/flux/docs/overview.html)或者父组件应该拥有 formData
状态和在 saveData
中调用 setState
自身,这将导致重新渲染 DOM 树的那部分。
先了解一下背景,我正在做一份问卷并决定开始学习 React.js。问卷的每个步骤都包括一个问题和一个 yes/no 单选按钮组,以及导航按钮。这是 jsfiddle。问题组件非常简单,我在父组件中将 formData 和保存数据函数传递给它。
以及问题部分的代码
var Question = React.createClass({
getInitialState: function() {
return {
}
},
createMarkup: function(html) {
return {
__html: html
};
},
render: function() {
var subtitle = this.props.subtitle || '';
var name = this.props.name;
if (this.props.formData[name] === undefined) {
var answer_yes = null;
var answer_no = null;
} else {
answer_yes = this.props.formData[name] == "yes" ? true : null;
answer_no = this.props.formData[name] == "no" ? true : null;
}
console.log(answer_yes);
console.log(answer_no);
return (
<div className="container-question">
<label className="default" dangerouslySetInnerHTML={this.createMarkup(this.props.question)}></label>
<span className="alert subtitle" dangerouslySetInnerHTML={this.createMarkup(subtitle)}></span>
<div className="form-group form-group-radio">
<div className="row">
<div className="col-xs-4">
<input type="radio" id={name + "_yes"} name={name} value="yes" defaultChecked={answer_yes} onChange={this.props.saveData}/><label htmlFor="yes">Yes</label><br></br>
<input type="radio" id={name + "_no"} name={name} value="no" defaultChecked={answer_no} onChange={this.props.saveData}/><label htmlFor="no">No</label>
</div>
</div>
</div>
</div>
);
}
});
问题是,当您 select 您对第一个问题的回答并点击下一步时,第二个问题的无线电控制随之改变,当您先回答第二个问题时也会发生同样的事情。我将 defaultChecked 的布尔变量存储为渲染函数中的局部变量,并将它们记录在控制台中。
我犯了什么明显的错误吗?感谢您的帮助。
这是一个更新后的 jsfiddle:https://jsfiddle.net/69z2wepo/8365/
问题是您在 React 中使用了所谓的 'uncontrolled component'。有关详细信息,请参阅此页面:https://facebook.github.io/react/docs/forms.html
为您的场景更改为受控组件意味着使用 checked
而不是 defaultChecked
。 defaultChecked
适用于不受控制的组件,其中输入控件(在您的情况下为单选按钮)的值不受组件的 props
或 render
方法控制。 React 的真正设计目的是使用受控组件,其中 props
/state
/render
完全驱动 UI 显示的内容。
从使用 defaultChecked
更改为 checked
时,您会注意到的第一件事是您将无法再更改 UI 中的无线电状态。发生这种情况的原因是因为虽然您的应用程序状态在您的 saveData
函数中被更改,但您的组件没有被重新渲染。
有几种不同的方法来处理这个问题。更新后的 jsfiddle 正在 saveData
期间重新呈现您的应用程序。理想情况下,这应该以不同的方式考虑。 saveData
应该从父组件中移出并进入 FormDataStore
概念(参见 React Flux 架构,https://facebook.github.io/flux/docs/overview.html)或者父组件应该拥有 formData
状态和在 saveData
中调用 setState
自身,这将导致重新渲染 DOM 树的那部分。