考虑这个例子:
var Field = React.createClass({
render: function () {
// never renders new value...
return (
<div>
<input type="text" defaultValue={this.props.value || ''} />
</div>
);
}
});
var App = React.createClass({
getInitialState: function () {
return {value: 'Hello!'};
},
changeTo: function (str) {
this.setState({value: str});
},
render: function () {
return (
<div>
<Field value={this.state.value} />
<button onClick={this.changeTo.bind(null, 'Whyyyy?')}>Change to "Whyyyy?"</button>
<button onClick={this.changeTo.bind(null, void 0)}>Change to undefined</button>
</div>
);
}
});
React.render(
<App />,
document.getElementById('app')
);
我想将值传递给defaultValue
作为哑输入组件的支柱。然而,它永远不会重新呈现它。
答案 0 :(得分:46)
如上所述,defaultValue
仅在表单的初始加载时设置。在那之后,它不会自然而然地#34;更新,因为意图只是设置初始默认值。
如果需要,可以通过将key
传递给包装器组件来解决此问题,例如在Field
或App
组件上,尽管在更实际的情况下,它可能会是一个form
组件。好的key
将是传递给表单的资源的唯一值 - 例如,存储在数据库中的id。
在简化的情况下,您可以在Field渲染中执行此操作:
<div key={this.props.value}>
<input type="text" defaultValue={this.props.value || ''} />
</div>
在一个更复杂的表格案例中,像这样的东西可能会得到你想要的东西,例如你的onSubmit动作提交给API但是停留在同一页面上:
const Form = ({item, onSubmit}) => {
return (
<form onSubmit={onSubmit} key={item.id}>
<label>
First Name
<input type="text" name="firstName" defaultValue={item.firstName} />
</label>
<label>
Last Name
<input type="text" name="lastName" defaultValue={item.lastName} />
</label>
<button>Submit!</button>
</form>
)
}
Form.defaultProps = {
item: {}
}
Form.propTypes = {
item: PropTypes.object,
onSubmit: PropTypes.func.isRequired
}
当使用不受控制的表单输入时,我们通常不会关注这些值,直到它们被提交为止,这就是为什么当你真正强制重新渲染它时更为理想的原因想要更新defaultValues(提交后,而不是每次更改单个输入)。
如果您还要编辑相同的表单并担心API响应可能会返回不同的值,则可以提供ID和时间戳之类的组合键。
答案 1 :(得分:12)
defaultValue 仅适用于初始加载。在那之后,它不会得到更新。您需要为 Field 组件维护状态:
var Field = React.createClass({
//transfer props to state on load
getInitialState: function () {
return {value: this.props.value};
},
//if the parent component updates the prop, force re-render
componentWillReceiveProps: function(nextProps) {
this.setState({value: nextProps.value});
},
//re-render when input changes
_handleChange: function (e){
this.setState({value: e.target.value});
},
render: function () {
// render based on state
return (
<div>
<input type="text" onChange={this._handleChange}
value={this.state.value || ''} />
</div>
);
}
});
答案 2 :(得分:4)
我相当肯定这与Controlled vs. Uncontrolled inputs有关。
如果我理解正确,由于您的<input>
不受控制(没有定义value
属性),因此该值将始终解析为初始化的值。在这种情况下Hello!
。
为了解决此问题,您可以添加value
属性并在onChange
期间设置它:
var Field = React.createClass({
render: function () {
// never renders new value...
return (
<div>
<input type="text" defaultValue={this.props.default || ''} value={this.props.value} />
</div>
);
}
});
Here is a plunker显示更改。
答案 3 :(得分:0)
我也遇到了这个问题,我所做的是在道具发生变化时手动更新输入值。将其添加到Field反应类:
componentWillReceiveProps(nextProps){
if(nextProps.value != this.props.value) {
document.getElementById(<element_id>).value = nextProps.value
}
}
您只需要在元素中添加一个id属性,以便找到它。
答案 4 :(得分:0)
问题在于:
onClick={this.changeTo.bind(null, 'Whyyyy?')}
我很好奇为什么要绑定null。
您想要绑定到'this',以便changeTo将在此对象中设置State。
试试这个
<button onClick={this.changeTo.bind(this, 'Whyyyy?')}>Change to "Whyyyy?"</button>
<button onClick={this.changeTo.bind(this, void 0)}>Change to undefined</button>
在Javascript中,当一个函数被调用时,它在调用它的范围内被调用,而不是它被写入的位置(我知道,似乎反直觉)。为了确保在你编写它的上下文中调用它,你需要'.bind(this)'。
要了解有关绑定和功能范围的更多信息,有很多在线设备(有些比其他设备好得多) - 您可能会喜欢这个:http://ryanmorr.com/understanding-scope-and-context-in-javascript/
如果您使用的是firefox或chrome,我还建议您使用React Dev工具,这样您就可以看到state.message没有改变: https://facebook.github.io/react/blog/2015/09/02/new-react-developer-tools.html
答案 5 :(得分:0)
使用条件渲染,然后组件将加载正确的初始值。像这个模块中的东西:
class MenuHeaderInput extends React.Component{
constructor(props){
super(props);
this.handleBlur = this.handleBlur.bind (this);
}
handleBlur (e) {
this.props.menuHeaderUpdate(e.target.value);
}
render(){
if (this.props.menuHeader) {
return (
<div className="w3-row w3-margin" onClick = {() => this.props.handleTitleClick (10)}>
<div className="w3-third" ><pre></pre></div>
<input
className = {"w3-third w3-input w3-jumbo " + EDIT_COLOR}
type = "text"
defaultValue = {this.props.menuHeader}
onBlur = {this.handleBlur}
/>
<div className="w3-third" ><pre></pre></div>
</div>
)
}
else {
return null;
}
}
}
答案 6 :(得分:0)
您可以有条件地进行输入,然后每次要强制更新defaultValue
时,只需要卸载输入,然后立即再次渲染。