Redux 形式的 handleSubmit:如何访问存储状态?

Redux-form handleSubmit: How to access store state?

在 redux 形式的 handleSubmit 函数中,它进行 Ajax 调用,Ajax 中需要来自 Redux 状态的一些属性(例如用户ID).

如果我想在表单的组件中定义 handleSubmit,这将很容易:只需调用 mapStateToProps 传递我需要的任何内容,然后从我的 this.props 中读取它handleSubmit.

但是,作为一名优秀的 React-Redux 开发人员,我编写了 单独的视图组件和容器 ,因此我的视图组件可以很简单,几乎没有或没有行为。因此,我想 在我的容器中定义 handleSubmit

同样,简单 - redux-form 的设置就是为了做到这一点。在mapDispatchToProps中定义一个onSubmit,表单会自动调用它。

除了,哦等等,在 mapDispatchToProps 中无法访问 redux 状态。

好的,没问题,我将把我需要的道具连同表单值一起传递到 handleSubmit

嗯,等等,使用这种机制不可能将任何数据传递到 handleSubmit!您获得一个参数 values,并且无法添加另一个参数。

这留下了以下没有吸引力的替代方案(我可以验证其中 1 和 2 的工作):

1 在表单组件中定义一个提交处理程序, 并从那里调用从 mapDispatchToProps 传入的我自己的自定义提交处理程序函数。这没关系,但需要我的组件从 redux 状态知道一些不需要显示表单的道具。 (这个问题不是 redux-form 独有的。)

dumbSubmit(values)
{
  const { mySubmitHandler, user} = this.props;
  mySubmitHandler(values, user);
}

<form onSubmit={ handleSubmit(this.dumbSubmit.bind(this)) }>

或者,更简洁地说,这都可以组合成一个箭头函数:

<form onSubmit={ handleSubmit((values)=>{mySubmitHandler(values, this.props.user);}

然后为了使这个处理程序完全不可知,它可以将整个 this.props 传递回自定义处理程序:

<form onSubmit={ handleSubmit((values)=>{mySubmitHandler(values, this.props);}

2 在 mergeProps 中定义 onSubmit 而不是 mapDispatchToProps,因此它可以访问 stateProps。 Dan Abramov recommends against using mergeProps (for performance reasons),所以这似乎不是最优的。

  function mergeProps(stateProps, dispatchProps, ownProps) {
  const { user } = stateProps.authReducer;
  const { dispatch } = dispatchProps;
  return {
    ...ownProps,
    ...dispatchProps,
    ...stateProps,
     onSubmit: (values) => {
       const { name, description } = values;
       const thing = new Thing(name, description, []);
       dispatch(createNewThing(thing, user.id));
     }
  }

3 将状态属性复制到 redux 表单字段中,这些字段不会映射到表单组件中的任何输入控件。这将确保它们可以在传递回 handleSubmitvalues 参数中访问。这看起来有点像 hack。

必须有更好的方法!

有没有更好的方法?

在花时间细化这个问题之后,选项 #1 实际上相当不错,在最后的迭代中(将所有道具传递回自定义处理程序的箭头函数)。它允许组件是无状态的,并且完全不知道它不使用的任何状态。所以我会称之为一个合理的答案。我很想听听您更好的解决方案!


在表单组件中使用箭头函数定义提交处理程序,并从那里调用我自己的从 mapDispatchToProps 传入的自定义提交处理程序函数。

<form onSubmit={ handleSubmit((values)=>{mySubmitHandler(values, this.props.user);}

然后为了让这个处理程序完全不可知,将整个 this.props 传递回自定义处理程序:

<form onSubmit={ handleSubmit((values)=>{mySubmitHandler(values, this.props);}

如果 Submit 函数只需要不属于表单的值和属性,我们可以只传回表单不使用的那些属性。在无状态组件中,这可能看起来像:

const Thing_Create = ({ fields: {name, description}, 
    error, 
    handleSubmit, 
    mySubmitHandler, 
    submitting, 
    onCancel, 
    ...otherprops}) => {
return (
<div>
  <form onSubmit={ handleSubmit((values)=>{
    mySubmitHandler(values, otherprops);}) }>
[rest of form definition would go here]

我可以通过绑定 this.

来解决这个问题

渲染中的某处()

<MyCustomFormComponent onSubmit={handleSubmit.bind(this)}/>

handleSumit

  handleSubmit(fields) {
    this.props.onSubmit(fields); //this is properly bound, HURRAY :-)
  }

MapDispatchToProps 优秀开发者:-)

const mapDispatchToProps = dispatch => ({
  onSubmit: (fields) =>
    dispatch({type: auth.actionTypes.LOGIN, payload: auth.api.login(fields)})
});

我找到的最佳方法与您提出的第一个解决方案非常相似。

利用 redux-form 传递的 handleSubmit prop 可以采用将用作 onSubmit prop 的函数,并使用部分应用程序传递任何其他参数需要 onSubmit.

动作创作者:

function updateUser(id, { name, lastname }) { ... }

假设组件得到一个 onUpdateUser 属性,它只是将参数直接传递给动作创建者。并且该组件还获得 user,一个具有 id 属性 的对象,我们希望将其与字段中的值一起传递给动作创建者。

组件

<form onSubmit={this.props.handleSubmit(this.props.onUpdateUser.bind(null, this.props.user.id))}>

这可以很容易地为无状态功能组件重写,只要您将它们放在 action creator 的左侧,就可以处理任意数量的参数,而且它不需要任何繁重的工作,只是 bind

这是 @stone's 的变体,但您可以通过函数式编程分解选项 1:

const mySubmitHandler = props => values => { /* ...code here */ }

<form onSubmit={ handleSubmit(mySubmitHandler(this.props)) }>

在这种情况下,mySubmitHandler 将 return 一个只接受一个参数的函数,该参数已经关闭了 this.props,因此无需明确提及 values handleSubmit 正在传递的论点。

您可以通过 ramda.

以更好、更易读的方式执行 mySubmitHandler 的柯里化
import { curry } from 'ramda';

const mySubmitHandler = curry((props, values) => { /* ...code here */ });

您可以更进一步,组合 handleSubmitmySubmitHandler

import { compose, curry } from 'ramda';

const handleSubmit = values => { /* ...code here */ };
const mySubmitHandler = curry((props, values) => { /* ...code here */ });
const onSubmit = compose(handleSubmit, mySubmitHandler);

<form onSubmit={ onSubmit(this.props) }>

请注意,onSubmit(this.props) return 是一个接受一个参数 (values) 并关闭 this.props 的函数,创建一个可以访问所有属性的函数它需要!