在进行Ajax调用的redux-form handleSubmit
函数中,Ajax中需要一些Redux状态的属性(例如用户ID)。
如果我想在表单组件中定义handleSubmit
,这很容易:只需调用mapStateToProps
即可传入我需要的内容,并从this.props
中读取它在我的handleSubmit
。
但是,像一个优秀的React-Redux开发人员一样,我编写单独的视图组件和容器,因此我的视图组件可以很简单,几乎没有行为。因此,我想在我的容器中定义handleSubmit 。
同样,简单的 - redux-form被设置为这样做。在onSubmit
中定义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 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-form字段,这些字段未映射到表单组件中的任何输入控件。这将确保在传递回values
的{{1}}参数中可以访问它们。这看起来像是一种黑客攻击。
有更好的方法吗?
答案 0 :(得分:13)
在最后一次迭代(将所有道具传递回自定义处理程序的箭头函数)中花费时间完善此问题之后,选项#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]
答案 1 :(得分:2)
我发现的最佳方式与您提出的第一个解决方案非常相似。
利用redux-form传递的handleSubmit
道具可以采用将用作onSubmit
道具的函数,并使用部分应用程序传递您需要的任何其他参数这一事实onSubmit
。
行动创作者:
function updateUser(id, { name, lastname }) { ... }
假设组件获得onUpdateUser
属性,只将参数直接传递给动作创建者。该组件还获得user
,这是一个具有id
属性的对象,我们希望将这些属性与字段中的值一起传递给操作创建者。
组件
<form onSubmit={this.props.handleSubmit(this.props.onUpdateUser.bind(null, this.props.user.id))}>
这可以轻松地为无状态功能组件重写,只要您将它们放在动作创建器的左侧,就可以适用于任何数量的参数,并且它不需要任何繁重的工作,只需{ {1}}
答案 2 :(得分:1)
这是@stone的answer的一种变体,但是您可以通过功能编程来分解选项1:
const mySubmitHandler = props => values => { /* ...code here */ }
<form onSubmit={ handleSubmit(mySubmitHandler(this.props)) }>
在这种情况下,mySubmitHandler
将返回仅包含一个已在this.props
上关闭的参数的函数,因此无需明确提及{{1} }正在传递。
您可以通过ramda以更好和更易读的方式执行values
的计算。
handleSubmit
您可以通过组成mySubmitHandler
和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)
上关闭的函数,从而创建了一个可以访问其所需所有属性的函数!