【问题标题】:What is the correct way to wire up an input field in Redux在 Redux 中连接输入字段的正确方法是什么
【发布时间】:2017-03-25 06:26:02
【问题描述】:

为了简单起见,我在 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 来获取提交时的值。这显然不是只读字段,所以我尝试将其更改为具有默认值。

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

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

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

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    当您使用带有valueattribute 集的输入元素时,它会成为“受控”组件。更详细的解释请看这个页面:

    https://facebook.github.io/react/docs/forms.html#controlled-components)

    长话短说,这意味着在每次渲染时,您都将 value 属性设置为 props 中的值,除非您还更新 redux 存储中的值,否则该值将保持不变)。

    当输入“不受控制”时(值属性未显式设置),其内部状态(值字符串)由浏览器隐式处理。

    如果出于某种原因您更喜欢将状态保留在本地,并且您不想在每次使用 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 存储同步。 但是,如果您想重复使用相同的表单来编辑商店中的现有食谱,这将无法正常工作。

    【讨论】:

    • 这完全符合我的预期……但希望这不是真的。对于一个可能有多个字段的表单来说,这似乎是一个很大的开销。
    • 查看我上次的编辑。您实际上不必使用valueonChange,但是您失去了通过 Redux 控制表单中数据的能力。不过有时也可以,这取决于您的需要。
    【解决方案2】:

    正如 React 在控制台中已经提到的,您必须提供一个“onChange”侦听器以使该字段可编辑。

    背后的原因是你提供的输入字段的 value 属性

    {this.props.recipe.name}
    

    当您在输入字段中键入时,此值不会更改。 由于这不会改变,因此您不会在输入字段中看到新值。 (这让你觉得它是不可编辑的。)

    这里要注意的另一件事是“recipe.name”应该转移到组件的状态,以便您可以在“onChange”侦听器中设置新状态。

    查看“setState”函数的用法。

    【讨论】:

      猜你喜欢
      • 2018-11-13
      • 1970-01-01
      • 2014-08-26
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      • 2014-05-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多