在Redux中连接输入字段的正确方法是什么

时间:2017-03-24 21:26:23

标签: reactjs redux

我在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。除此以外,   设置onChangereadOnly。检查渲染方法   RecipeEditor

这是有道理的,但我不想要onChange事件,我会使用ref来获取提交的值。它显然不是一个只读字段,所以我尝试将其更改为defaultValue。

<input type="text" ref="_name" defaultValue={this.props.recipe.name} />

这更接近我正在寻找的行为,但现在这仅在安装控件时设置配方,并且在选择新配方时不再更新。

解决方案是否在每个设置状态的输入字段上都有一个处理程序,然后在提交中,获取所有状态并更新配方?

2 个答案:

答案 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;的用法功能