30

在进行 Ajax 调用的 redux-formhandleSubmit函数中,Ajax 中需要一些来自 Redux 状态的属性(例如用户 ID)。

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

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

再次,简单的 - redux-form 被设置为做到这一点。定义一个onSubmitin mapDispatchToProps,表单会自动调用它。

除了,哦等等,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 建议不要使用 mergeProps(出于性能原因),所以这似乎不是最理想的。

  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-form 字段中。这将确保它们可以在values传递回的参数中访问handleSubmit。这似乎是一种黑客行为。

一定有更好的办法!

有没有更好的办法?

4

4 回答 4

18

在花时间细化这个问题之后,选项 #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]
于 2016-05-31T23:00:51.043 回答
2

我发现的最好方法与您提出的第一个解决方案非常相似。

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

动作创建者:

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

假设组件获得了一个onUpdateUser属性,该属性只是将参数直接传递给动作创建者。并且该组件还获得user了一个对象,该对象具有id我们想要传递给动作创建者的属性以及字段中的值。

零件

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

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

于 2017-02-28T04:40:14.983 回答
1

我能够通过绑定解决这个问题this

在 render() 的某个地方

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

手柄Sumit

  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)})
});
于 2017-02-24T03:21:33.227 回答
1

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

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

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

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

您可以通过ramdamySubmitHandler以更好、更易读的方式执行柯里化。

import { curry } from 'ramda';

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

handleSubmit您可以通过编写和更进一步mySubmitHandler

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)返回一个接受一个参数 ( values) 并已关闭this.props的函数,创建一个可以访问它需要的所有属性的函数!

于 2019-08-23T09:19:15.270 回答