我在Redux应用程序中有以下组件用于配方,为了简单起见,目前只有一个名称。
class RecipeEditor extends Component {
onSubmit = (e) => {
e.preventDefault()
this.props.updateRecipe(this.props.recipe, { name: this.refs._name.value })
}
render = () => {
if (!this.props.recipe) {
return <div />
}
return (
<div>
<form onSubmit={this.onSubmit}>
<label>Name: </label>
<input type="text" ref="_name" value={this.props.recipe.name} />
<input type="submit" value="save" />
</form>
</div>)
}
static propTypes = {
recipe: React.PropTypes.shape({
name: React.PropTypes.string.isRequired
})
}
}
这给了我一个编辑器,其中包含一个无法编辑的文本框。控制台中也有警告:
警告:表单propType失败:您为表单提供了
value
道具 没有onChange
处理程序的字段。这将呈现为只读 领域。如果该字段应该是可变的,请使用defaultValue
。除此以外, 设置onChange
或readOnly
。检查渲染方法RecipeEditor
。
这是有道理的,但我不想要onChange
事件,我会使用ref
来获取提交的值。它显然不是一个只读字段,所以我尝试将其更改为defaultValue。
<input type="text" ref="_name" defaultValue={this.props.recipe.name} />
这更接近我正在寻找的行为,但现在这仅在安装控件时设置配方,并且在选择新配方时不再更新。
解决方案是否在每个设置状态的输入字段上都有一个处理程序,然后在提交中,获取所有状态并更新配方?
答案 0 :(得分:1)
当您使用设置了value
属性的输入元素时,它将成为一个受控制的&#34;零件。有关更详细的说明,请参阅此页:
https://facebook.github.io/react/docs/forms.html#controlled-components)
长话短说,这意味着在每个渲染中,您将value属性设置为props中的值,除非您还更新redux存储中的值,否则它将保持不变。
当输入是&#34;不受控制的&#34;相反(值属性未显式设置),其内部状态(值字符串)由浏览器隐式处理。
如果出于某种原因,您希望在本地保持状态,并且每次使用onChange更改值时都不想发送redux操作,您仍然可以使用React组件状态自行管理状态并调度操作提交:
class RecipeEditor extends Component {
state = {
recipeName: ''
}
onSubmit = (e) => {
e.preventDefault()
this.props.updateRecipe(this.props.recipe, { name: this.state.recipeName })
}
handleNameChange = (e) => {
this.setState({ recipeName: e.target.value })
}
render = () => {
if (!this.props.recipe) {
return <div />
}
return (
<div>
<form onSubmit={this.onSubmit}>
<label>Name: </label>
<input type="text" ref="_name" value={this.state.recipeName} onChange={this.handleNameChange} />
<input type="submit" value="save" />
</form>
</div>)
}
static propTypes = {
recipe: React.PropTypes.shape({
name: React.PropTypes.string.isRequired
})
}
}
在此示例中,只要输入值发生更改,您就会将当前值存储在状态中。调用setState
会触发一个新的渲染,在这种情况下,它会将值设置为更新的渲染。
最后,请注意,如果您不需要将输入值设置为特定值,则不必使用onChange
。在这种情况下,您可以删除value
属性,然后使用refs
。这意味着,如果您在代码中的其他位置更改存储在Redux状态中的值,则您将无法看到输入中反映的更改。正如您所见,您仍然可以使用intitalValue
将初始值设置为特定的值,它只是不会与您的redux商店同步。
但是,如果您希望重复使用相同的表单来编辑商店中现有的食谱,则效果不会很好。
答案 1 :(得分:0)
正如React在控制台中已经提到的那样,你必须提供一个&#34; onChange&#34;监听器使该字段可编辑。
背后的原因是您提供的输入字段的value属性
{this.props.recipe.name}
键入输入字段时,此值不会更改。 由于这不会发生变化,因此您无法在输入字段中看到新值。 (这让你觉得它不可编辑。)
这里要注意的另一件事是&#34; recipe.name&#34;应该转移到你的组件的状态,以便你可以设置一个新的状态&#34; onChange&#34;监听器。
查看&#34; setState&#34;的用法功能