Javascript 设置状态触发道具更改
示例组件从定义组件接收数据(示例列表)。由于这些示例可以由用户编辑,因此它们被放置在状态窗体中,状态窗体还允许我们在每次状态更改时创建/删除其他字段 在输入的每次击键(handleChangeExample函数)时,状态都会改变,但属性(props.examples)似乎也会更新,我不明白为什么会这样 我认为示例组件属性应该在整个周期中保持不变/不变,除非我们显式保存块(saveBlock函数),这反过来会从父定义组件触发saveExamples函数Javascript 设置状态触发道具更改,javascript,reactjs,Javascript,Reactjs,示例组件从定义组件接收数据(示例列表)。由于这些示例可以由用户编辑,因此它们被放置在状态窗体中,状态窗体还允许我们在每次状态更改时创建/删除其他字段 在输入的每次击键(handleChangeExample函数)时,状态都会改变,但属性(props.examples)似乎也会更新,我不明白为什么会这样 我认为示例组件属性应该在整个周期中保持不变/不变,除非我们显式保存块(saveBlock函数),这反过来会从父定义组件触发saveExamples函数 var Examples = React.c
var Examples = React.createClass({
getInitialState: function() {
return {
examples: this.props.examples
}
},
editBlock: function(event) {
// this.setState({examples: this.props.examples});
this.setState({editingBlock: !this.state.editingBlock});
},
saveBlock: function(event) {
var that = this;
var filtered_examples = [];
this.state.examples.forEach(function(example) {
if (example !== '') {
filtered_examples.push(example);
}
});
this.props.saveExamples(filtered_examples);
},
handleChangeExample: function(i) {
var updated_examples = this.state.examples;
updated_examples[i] = this.refs['example_' + i].getDOMNode().value.trim();
this.setState({examples: updated_examples});
},
render: function() {
var that = this;
var fields = {};
console.log(this.props.examples);
console.log(this.state.examples);
this.state.examples.forEach(function(example, i) {
if (example !== '') {
fields['example-' + i] =
<li className='editing__entry'>
<input type='text'
key={i}
ref={'example_' + i}
onChange={that.handleChangeExample.bind(null, i)}
defaultValue={example} />
</li>;
}
});
fields['example-' + (this.state.examples.length+1)] =
<li className='editing__entry'>
<input type='text'
key={this.state.examples.length+1}
ref={'example_' + (this.state.examples.length+1)}
onChange={that.handleChangeExample.bind(null, (this.state.examples.length+1))}
defaultValue='' />
</li>;
return (
<section className='definition__examples block'>
<div className='editing'>
<ul className='editing__fields'>
{fields}
</ul>
</div>
<button onClick={this.saveBlock} className='button--primary--small'>Save changes</button>
</section>
);
}
});
var Definition = React.createClass({
getInitialState: function() {
return {
examples: this.props.definition.examples
}
},
saveExamples: function(examples) {
this.setState({examples: examples});
},
render: function() {
var editingMode = this.props.editingMode;
var object = this;
return (
<li className='definition'>
<Examples editingMode={editingMode}
examples={this.state.examples}
saveExamples={this.saveExamples} />
</li>
);
}
});
module.exports = Definition;
var Examples=React.createClass({
getInitialState:函数(){
返回{
示例:this.props.examples
}
},
editBlock:函数(事件){
//this.setState({examples:this.props.examples});
this.setState({editingBlock:!this.state.editingBlock});
},
存储块:函数(事件){
var=这个;
var过滤_示例=[];
this.state.examples.forEach(函数(示例){
如果(例如!=''){
过滤的示例。推送(示例);
}
});
this.props.saveExamples(过滤的示例);
},
HandleChange示例:函数(i){
var更新的_示例=this.state.examples;
更新的_examples[i]=this.refs['example_'+i].getDOMNode().value.trim();
this.setState({examples:updated_examples});
},
render:function(){
var=这个;
变量字段={};
log(this.props.examples);
log(this.state.examples);
this.state.examples.forEach(函数(示例,i){
如果(例如!=''){
字段['example-'+i]=
;
}
});
字段['example-'+(this.state.examples.length+1)]=
;
返回(
{fields}
保存更改
);
}
});
变量定义=React.createClass({
getInitialState:函数(){
返回{
示例:this.props.definition.examples
}
},
保存示例:函数(示例){
this.setState({examples:examples});
},
render:function(){
var editingMode=this.props.editingMode;
var object=这个;
返回(
);
}
});
module.exports=定义;
您看到这种行为是因为this.state.examples
只是对this.props.examples
的引用
this.props.examples
正在更新,原因与纯JavaScript中的预期行为相同:
> var a = [ 'abc', 'def', 'ghi' ];
undefined
> a
[ 'abc', 'def', 'ghi' ]
> var b = a;
undefined
> b
[ 'abc', 'def', 'ghi' ]
> b[1] = 'DEF';
'DEF'
> b
[ 'abc', 'DEF', 'ghi' ]
> a
[ 'abc', 'DEF', 'ghi' ]
有两种方法可以解决这个问题。一种是创建this.props.examples
的副本,并将其设置为this.state.examples
(您可以通过Array.prototype.slice执行此操作):
我认为这在您的情况下会起作用,因为示例
只是一个字符串数组。但是,slice
只会创建数组的浅层副本,因此如果元素是对象或数组,您仍然会更新this.props.examples
另一个选项是用于更新您的状态。您可能还想看看
下面是一个简化的示例,说明如何使用不变性帮助程序执行您正试图执行的操作:
/**@jsx React.DOM*/
var SomeComponent=React.createClass({
getInitialState:函数(){
返回{
示例:this.props.examples,
}
},
_handleChange:函数(索引,e){
var updateObj={};
updateObj[index]={$set:e.target.value};
var newData=React.addons.update(this.state.examples,updateObj);
this.setState({示例:newData});
},
render:function(){
返回(
道具:
{JSON.stringify(this.props.examples,null,2)}
声明:
{JSON.stringify(this.state.examples,null,2)}
);
}
} );
React.renderComponent(,document.getElementById('main'));
getInitialState: function() {
return {
examples: this.props.examples.slice()
}
}
/** @jsx React.DOM */
var SomeComponent = React.createClass( {
getInitialState : function() {
return {
examples : this.props.examples,
}
},
_handleChange : function( index, e) {
var updateObj = {};
updateObj[ index ] = { $set : e.target.value };
var newData = React.addons.update( this.state.examples, updateObj );
this.setState( { examples : newData } );
},
render : function() {
return (
<div>
<input onChange={this._handleChange.bind(this, 0)}/><br/>
<input onChange={this._handleChange.bind(this, 1)}/><br/>
props:
<pre>{JSON.stringify(this.props.examples,null,2)}</pre>
state:
<pre>{JSON.stringify(this.state.examples,null,2)}</pre>
</div>
);
}
} );
React.renderComponent(<SomeComponent examples={ [ "ABC", "DEF" ] } />, document.getElementById( 'main' ) );