作为帮助我学习ReactJS的一种方式,我正在设置一些应该很容易的东西,但事实证明对我来说有些棘手。
我想在ReactJS中设置一些托管复选框组。在HTML中,复选框“字段”实际上由许多共享公共名称属性的input type=“checkbox”元素组成。据我所知,这只是一种UI元素,应该适合ReactJS的组合特性。
我有两个组件:
首先,Checkbox Field是针对复选框组中的每个单独条目-即,每个输入类型="复选框"的超文本标记语言元素。
其次,CheckboxFieldGroup用于每组复选框条目,即共享公共名称属性的每一组HTML元素。CheckboxFieldGroup组件根据传入的初始道具创建许多CheckboxField组件。
状态在CheckboxFieldGroup组件中管理,而不是在单个CheckboxField级别。据我所知,您应该将状态管理为有意义的最高级别。对我来说,在CheckboxFieldGroup级别上使用它更有意义。
当CheckboxFieldGroup第一次运行时,它的初始状态将从它的初始道具(也是一个数组)创建为一个数组。render方法(实际上是renderChoices方法)循环遍历其状态数组,并将每个状态成员的属性向下传递给CheckboxField组件作为后者的支柱。当用户勾选/取消勾选其中一个复选框时,该事件通过回调传递给其所有者CheckboxFieldGroup的handleChange方法。此方法通过询问其id属性来确定哪些复选框已更改,然后通过setState()调用对CheckboxFieldGroup状态数组的正确成员进行相应更改。这将导致CheckboxFieldGroup自动重新渲染,新的状态数组将传递给各个CheckboxField组件,因此所有内容都是同步的。
/** @jsx React.DOM */
var CheckboxField = React.createClass({
propTypes: {
values: React.PropTypes.object.isRequired
},
getDefaultProps: function () {
return {
values: {
label: "Place holder text"
}
};
},
render: function() {
return (
<label htlmFor={this.props.values.id}>
<input type="checkbox"
name={this.props.values.name}
id={this.props.values.id}
value={this.props.values.value}
checked={this.props.values.checked}
onChange={this.handleChange} />
{this.props.values.label} <br />
</label>
);
},
handleChange: function(event) {
// Should use this to set parent's state via a callback func. Then the
// change to the parent's state will generate new props to be passed down
// to the children in the render().
this.props.callBackOnChange(this, event.target.checked);
}
});
var CheckboxFieldGroup = React.createClass({
propTypes: {
defaultValues: React.PropTypes.object.isRequired
},
getInitialState: function () {
// default props passed in to CheckboxFieldGroup (this componenent) will be used to set up the state. State
// is stored in this component, and *not* in the child CheckboxField components. The state store in this
// component will, in turn, generate the props for the child CheckboxField components. When the latter
// are updated (i.e. clicked) by the user, then the event will call the handleChange() function in
// this component. That will generate update this component's state, which in turn will generate
// new props for the child CheckboxField components, which will cause those components to re-render!
var that = this;
var initStateArray = this.props.defaultValues.valuesArray.map(function(choice, i) {
var tempObj = {
name: that.props.defaultValues.name,
value: choice.value,
label: choice.label,
id: _.uniqueId("choice"),
checked: choice.checked
};
return tempObj;
});
return {valuesArray: initStateArray};
},
renderChoices: function() {
var that = this; // Could also use .bind(this) on our map() function but that requires IE9+.
return this.state.valuesArray.map(function(choice, i) {
return CheckboxField({
values: {
name: that.props.defaultValues.name,
value: choice.label,
label: choice.label,
id: choice.id,
checked: choice.checked
},
callBackOnChange: that.handleChange
});
});
},
render: function () {
return (
<form>
{this.renderChoices()}
</form>
);
},
handleChange: function(componentChanged, newState) {
// Callback function passed from CheckboxFieldGroup (this component) to each of the
// CheckboxField child components. (See renderChoices func).
var idx = -1;
var stateMemberToChange = _.find(this.state.valuesArray, function(obj, num) {
idx = num;
return obj.id === componentChanged.props.values.id;
});
// Threw an error when I tried to update and indiviudal member of the state array/object. So, take a copy
// of the state, update the copy and do a setState() on the whole thing. Using setState() rather than
// replaceState() should be more efficient here.
var newStateValuesArray = this.state.valuesArray;
newStateValuesArray[idx].checked = newState;
this.setState({valuesArray: newStateValuesArray}); // Automatically triggers render() !!
},
getCheckedValues: function() {
// Get an array of state objects that are checked
var checkedObjArray = [];
checkedObjArray = _.filter(this.state.valuesArray, function(obj){
return obj.checked;
});
// Get an array of value properties for the checked objects
var checkedArray = _.map(checkedObjArray, function(obj){
return obj.value;
});
console.log("CheckboxFieldGroup.getCheckedValues() = " + checkedArray);
},
componentDidMount: function() {
this.getCheckedValues();
},
componentDidUpdate: function() {
this.getCheckedValues();
}
});
var defaults = {
name : "mikeyCheck",
valuesArray : [{
label : "My Checkbox Field",
value: "MyCheckboxField",
checked : false
}, {
label : "My Other Checkbox Field",
value : "MyOtherCheckboxField",
checked : false
}, {
label : "Yet Another Checkbox Field",
value : "YetAnotherCheckboxField",
checked : true
},{
label : "Yes, it's a fourth checkbox field",
value : "YesItsAFourthCheckboxField",
checked : false
}]
};
React.renderComponent(<CheckboxFieldGroup defaultValues={defaults} />, document.getElementById("main"));
这一切都很好,下面是一个正在运行的JSFiddle。
但我觉得我在这里做了很多错事。
事先非常感谢你的帮助。是的,我有谷歌,并且仔细阅读了文档。我还购买并阅读了《开发React Edge》一书,这本书目前在一个领域中排名第一!
对于问题1,我有同样的感觉,当我第一次使用反应来构建我的第一个组件,猜是这样的?哈哈
对于问题2和问题3,我只将选中的保存在状态中,其余信息保留在道具中。然后在处理更新时,我只将某些复选框设置为true/false。
http://jsfiddle.net/p0s58exh/4/
getInitialState: function () {
var that = this;
var states = {};
_.map(this.props.defaultValues.checkboxes, function (choice, key) {
states[key] = choice.checked;
});
return states;
},
请记住将
key
添加到子数组元素中,以便反应准确地知道要更新哪个元素。
return _.map(this.props.defaultValues.checkboxes, function (choice, key) {
return CheckboxField({
key: key,
values: {
name: that.props.defaultValues.name,
value: key,
label: choice.label,
id: choice.id,
checked: that.state[key]
},
callBackOnChange: that.handleChange
});
});
这是我的状态 我试图做的是,每当选中或未选中复选框时,我将相应的复选框设置为true/false。根据每个复选框的这个布尔值,我过滤出,然后在UI上呈现它。当单击复选框时,我能够筛选结果,但当未选中复选框时,我无法显示所有结果。当复选框发生更改时,我就是这样处理的。 我知道我没有正确地处理状态,在这种情况下我能做什么。为了更好地参考,这里是完整的搜索结果代码。
问题内容: 在React中为复选框状态分配默认值后,我无法更新复选框状态。 分配后,我无法通过单击取消选中/选中来交互复选框状态。 问题答案: 如果仅使用创建复选框,则使用该属性 。 归功于@nash_ag
这会找到我想要的节点吗?如果没有,我如何获得节点并正确地更改属性? 谢谢。马格努斯
问题内容: 我遇到这样的情况,我想更新一些输入为复选框的数据,我在下面尝试了此代码。数据已保存在数据库中,但数据已保存在另一行中, 例如:我为BirdA选中了红色,黄色和灰色,同时为BirdD选中了黑色和蓝色。在数据库中,BirdA的颜色正确保存,但是第二只鸟的深色和蓝色保存在BirdB上( 应保存在BirdD上 ) 我想解决上面的问题,因此数据应保存在数据库中的正确位置。请在下面检查我的代码:
我试图创建一个表单,该表单顶部有一个复选框,当用户选中该复选框时,它会选择其他特定的复选框,但不是所有复选框。我很难通过反复试验或搜索找到答案。我唯一能找到的就是“全选”选项。不是我想要的。 理想情况下,当用户选中“管理包”旁边的复选框时,我想要“Chrome外观组”和“远程启动” 下面是代码和我在这方面的基本尝试,但它不起作用。提前谢谢。 超文本标记语言: Javascript 我不知道这个Ja
问题内容: 我在尝试创建一个使用React选择和取消选择其他单个复选框(全选/全选)的复选框时遇到了一个小问题。我已阅读http://facebook.github.io/react/docs/forms.html,发现 受控 和 非受控 s 之间存在差异。我的测试代码如下: “全局选择器”按预期方式工作:选中后,将选中所有其他检查。问题在于,当单击其他复选框之一时,不会触发处理程序。 我不知道进