【问题标题】:How to properly manage forms in React/Redux app如何在 React/Redux 应用程序中正确管理表单
【发布时间】:2016-07-11 18:39:05
【问题描述】:

我正在关注一些关于 React/Redux 的教程。 我不清楚的部分是输入表单。 我的意思是如何处理更改以及在哪里管理状态 这是一个非常简单的表单,只有一个字段。

export default class UserAdd extends React.Component {

static propTypes = {
    onUserSubmit: React.PropTypes.func.isRequired
}

constructor (props, context) {
    super(props, context);
    this.state = {
        name: this.props.name
    };
}

render () {
    return (
        <form
            onSubmit={e => {
                e.preventDefault()
                this.handleSubmit()
            }}
        >
            <input
                placeholder="Name"
                onChange={this.handleChange.bind(this)}
            />
            <input type="submit" value="Add" />
        </form>
    );
}

handleChange (e) {
    this.setState({ name: e.target.value });
}

handleSubmit () {
    this.props.onUserSubmit(this.state.name);
    this.setState({ name: '' });
}
}

我觉得这像是在打破 Redux 哲学,因为一个表示组件正在更新状态,对吗? 这是要与表示组件耦合的连接组件。

const mapDispatchToProps = (dispatch) => {
    return {
        onUserSubmit: (name) => {
            dispatch(addUser(name))
        }
    }
}

const UserAddContainer = connect(
    undefined,
    mapDispatchToProps
)(UserAdd)

这是正确的做法,还是我把事情搞混了? 在 UserAdd 组件中调用 setState 并在按下每个键时更新状态 (handleChange) 是否正确?

谢谢

【问题讨论】:

    标签: javascript forms reactjs redux react-redux


    【解决方案1】:

    有一个不错的库Redux Form 用于通过以 Redux 方式更新全局存储来处理表单。有了它的帮助,您不必为每个输入设置操作,只需为整个表单及其状态设置操作。看看吧。

    这个库的主要原理是通过调度 redux 操作来更新输入值,而不是使用 setState 东西。对于应用程序中的每个表单,在全局状态中都有一个单独的property。每个bluronChangesubmit 事件都会调度一个改变状态的动作。动作创建者对所有表单都是通用的,不需要为每个表单单独声明它们,只需将有效负载中的表单 id 或名称传递给减速器,这样它就可以知道应该更新哪个表单的属性。

    例如。应该将属性form 设置为应用程序状态中的普通对象。应用程序中的每个新表单都应将其状态存储在其中。让我们给你的表单一个名称属性,所以它应该作为我们的标识符。

    render () {
    return (
        <form
            name="AForm"
            onSubmit={e => {
                e.preventDefault()
                this.handleSubmit()
            }}
        >
            <input
                name="name"
                placeholder="Name"
                onChange={this.handleChange.bind(this)}
            />
            <input type="submit" value="Add" />
        </form>
    );
    

    }

    由于它只有一个属性 Nameform 状态现在应该具有如下结构:

    form: {
      AForm: {
         Name: {
           value: '',
           error: ''
         }
      }
    } 
    

    另外,应该有一个动作创建者:

    export function onFormFieldChange(field) {  
      return {
        type: "redux-form/CHANGE"
        field: field.name
        value: field.value,
        form: field.form
      }
    }
    

    所有需要的数据都应该作为有效负载传递,因此reducer 现在将知道要更新什么表单和什么字段。

    现在,当表单组件被连接时,这个动作创建者应该被设置为一个属性:

    import { onFormFieldChange } from `path-to-file-wit-actions` 
    const mapStateToProps = (state, ownProps) => {
      const { AForm } = state.form
      return {
       name: AForm.name
      }
    } 
    const mapDispatchToProps = (dispatch) => {
      return {
        onChange: (e) => {
          dispatch(onFormFieldChange({
            field: 'name',
            value: e.target.value,
            form: 'AForm'
          }))
        },
        onUserSubmit: (name) => {
          dispatch(addUser(name))
        }
      }
    }
    
    const UserAddContainer = connect(
      undefined,
      mapDispatchToProps
    )(UserAdd)
    

    在组件中,字段值和onChange 事件处理程序现在应该从道具中获取:

    <input placeholder="Name" name="this.props.name.value"  onChange={this.props.handleChange.bind(this)} />
    

    因此,表单正在以 “Redux” 方式处理。每次按键时,全局状态都会更新,输入会用它的新值重新渲染。其他事件也应该做类似的事情,如onBLuronFocusonSubmit 等。由于工作量很大,使用 Redux Form 会更舒服。

    这是一个非常粗略的例子。几乎每一行代码都可以被增强,希望你能明白什么意思。

    【讨论】:

    • 我看到了那个库,但我想从头开始理解表单,首先..
    • 更新了我的答案,增加了一些解释。
    • 感谢您非常详细的回答。那我就搬到那个图书馆去。
    • 抱歉,与official one 相比,您的示例不清楚。你不应该调用 reduxForm 而不是 Redux.connect 吗?
    • 在我的示例中我没有使用 reduxForm,我试图展示如何以redux 的方式管理表单。该方法与reduxForm 实现非常相似。
    【解决方案2】:

    我通常使用this.setState() 将我的表单状态存储在表单组件中,并且只使用完整的表单对象触发一个操作,该操作将传递给某种POST ajax 调用。

    【讨论】:

    • 你的意思是不使用一个组件,而不是两个连接的组件?
    • 我将有一个单一的Form 组件,其中包含所有表单逻辑,并且还具有由所有输入填充的自己的内部状态。然后你可以有一个onSubmit 序列化你的Form 状态中的所有数据并用它触发一个动作。
    • 好的,很清楚。但这不是打破 redux 哲学吗?我们不应该在只有容器处理状态的 2 个组件(表示和容器)中解耦吗?
    猜你喜欢
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 2019-04-27
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多