击中一个路障,我正在寻求帮助。我开始从我的React组件中移出更多的“状态”pojo,因为例如我不确定现在应该如何利用我的pojo的setter方法(可能需要setter方法来验证等)。我现在发现自己要么违反React docs的警告,要么永远不要直接触摸this.state,要么将大部分代码除了渲染 - 包括状态 - 在React组件之外移动到我自己的js变量/对象中(并保持对渲染对象的引用然后使用forceUpdate()重新渲染)。什么是自由使用我想要的普通旧js数据/模型对象的推荐方法,包括使用setter方法?
这个准确的示例,我想要一个表单支持数据对象,展示了我面临的这种差异:http://jsfiddle.net/jL0rf0ed/与http://jsfiddle.net/rzuswg9x/。还粘贴了下面第一个代码。
至少,我有这个具体的问题:在this.state的自定义/手动更新之后,会有一个this.setState(this.state)行,它来自React组件和一个组件。 forceUpdate()行可能来自React组件外部,与标准this.setState({someKey:someValue})一样快速正确地工作?
感谢。
//props: dataObj, handleInputChange
test.ComponentA = React.createClass({
getInitialState: function() {
return {
age: 21,
email: 'a@b.com', //TODO make members private
setEmail: function(val) { //TODO utilize this
this.email = val;
if(val.indexOf('@') == -1) {
//TODO set or report an error
}
}
}
},
handleInputChange: function(e) {
this.state[e.target.name]=e.target.value; //defying the "NEVER touch this.state" warning (but it appears to work fine)!
this.setState(this.state); //and then this strange line
},
render: function() {
return (
<div>
<input type='text' name='age' onChange={this.handleInputChange} value={this.state.age}></input>
<input type='text' name='email' onChange={this.handleInputChange} value={this.state.email}></input>
<div>{JSON.stringify(this.state)}</div>
</div>
);
}
});
React.render(<test.ComponentA />, document.body);
答案 0 :(得分:1)
对于粘贴代码段中的代码示例,您可以执行以下操作。
handleInputChange: function(e) {
var updates = {};
updates[e.target.name] = e.target.value;
this.setState(updates);
},
在第二个示例中,您不应该从组件本身外部调用forceUpdate
或setState
。正确的方法是将状态包含在任何呈现组件的内容中,并将数据作为props传递。
通常这意味着你有一个包装器组件。
var RootComponent = React.createClass({
getInitialState: ...
onInputChange: function() {
this.setState({yourKey: yourValue});
},
render: function() {
return <SubComponent yourKey={this.state.yourKey} onInputChange={this.onInputChange} />;
}
};
在您的情况下,我建议您创建此包装器组件。另一种解决方案是将相同的组件重新呈现到同一个DOM节点中。
test.handleInputChange = function(e) {
// update test.formPojo1 here
React.render(<test.ComponentA dataObj={test.formPojo1} handleInputChange={...} />);
}
因为它是相同的组件类和DOM节点,所以React会将其视为更新。
答案 1 :(得分:-1)
商店是一个非常有针对性的POJO。而且我发现使用Store隐喻而不使用整个Flux非常简单。
这是我从我们的一个生产React应用程序中提取的商店:
ChatMessageStore = {
chatMessages: [],
callbacks: [],
getAll: function() {
return this.chatMessages;
},
init: function() {
this.chatMessages = window.chat_messages.slice();
return this.emitChange();
},
create: function(message) {
this.chatMessages.push(message);
return this.emitChange();
},
emitChange: function() {
return this.callbacks.forEach(callback, function() {
return callback();
});
},
addChangeListener: function(callback) {
return this.callbacks.push(callback);
},
removeChangeListener: function(callback) {
return this.callbacks = _.without(this.callbacks, callback);
}
};
在您的组件中,您现在可以在商店中查询其数据:
var Chat = React.createClass({
componentWillMount: function() {
return ChatMessageStore.addChangeListener(this._onChange);
},
componentWillUnmount: function() {
return ChatMessageStore.removeChangeListener(this._onChange);
},
getInitialState: function() {
return this.getMessageState();
},
getMessageState: function() {
return {
messages: ChatMessageStore.getAll()
};
}
});
组件向Store注册回调,该回调在每次更改时触发,更新组件并遵守“不要修改状态”的规则。