https://codepen.io/anon/pen/vwzGYY?editors=0011
根据我的研究,似乎我需要一种完全不同的方法。也许你可以建议一个?
我正在使用Redux-Form(技术上是较旧的版本,但API的 问题似乎真的很稳定。我们可以在到达那儿时烧掉那座桥。)为某种搜索结果列表设置一些“过滤器”。
尤其是,由于我希望页面能够链接,所以我还通过React-Router在URL查询参数中设置表单内容,或者首先通过类似的机制在页面加载时设置表单内容。
到目前为止,唯一的字段是“ organization_name”,这是一个文本字段,用于设置查询参数值,并触发/endpoint?name={some_name}
的API请求。
例如
<Field
name="organization_name"
component="input"
type="text"
placeholder="Organization Name"
value={value}
/>
我已经尝试了几件事,但这是最近的镜头:
我从默认道具中抢走reset
,change
和其他东西。我根据需要传递了handleSubmit
。
handleSubmit
正常工作,进行一些状态更新,使用React Router设置/推送URL查询参数,然后进行新的API调用/更新显示新结果! !
从长远来看,我希望有一个“重置过滤器”按钮,该按钮可将所有过滤器值重新设置为默认值(例如,将“名称”值设置为空字符串),然后重新提交表单(因此触发handleSubmit)。
我首先尝试实现的是一个按钮,例如:
<button
name="reset_filters_button"
type="button"
onClick={resetAndSubmit}
disabled={pristine || submitting}
>
Clear Search
</button>
resetAndSubmit
在表单容器上的定义如下:
const resetAndSubmit = event => {
reset();
handleSubmit();
};
使用Chrome开发工具调试器,我可以清楚地看到,该reset
方法被调用,并返回它的dispatch(...)
事件。但是,表单和状态值在 handleSubmit()
运行并提交表单之前不会更新。
我认为这可能与优先考虑Submit事件有关吗?
我也尝试过搞怪,例如导入change
(容器的默认属性)并定义重置按钮,从而:
<button
name="reset_filters_button"
type="button"
onClick={() => {
change('organization_name', '');
methodThatDispatchesSubmitAction();
}}
disabled={pristine || submitting}
>
Clear Search
</button>
哪个(如果我删除了methodThatDispatchesSubmitAction()
)可以正确地将字段值设置回空白,因此技术上也使表格再次“原始”。
methodThatDispatchesSubmitAction()
(如果不太明显)通过dispatchToProps
绑定到父对象,并传递到表单容器,该容器使用“远程提交”建议,例如
// organization_list_filter == name of the Redux-Form to submit.
dispatch(submit('organization_list_filter'));
如何正确重置表单并提交其默认/空值?
每次我分发或直接调用Redux Form'submit'时,最终都会在之前提交表单,以清除状态或UI中的值。 我已经通过调试器进行了调试,并且不会跳过对reset
或change
的呼叫。这就像一个异步/竞赛问题,但是我承认在这种情况下,我肯定不属于我。
我只是直截了当地做错了吗?
答案 0 :(得分:0)
这绝对是一个竞争条件问题(或者因为我们实际上并不在处理线程,所以是一个事件顺序问题)。
在当前示例不起作用时使用methodThatDispatchesSubmitAction
的原因是,因为分派的操作具有直接从Redux存储读取数据的好处。您的示例不是从redux存储中读取数据,而是从传入的属性中读取数据。是的,此属性来自redux存储,但是您看到的问题是尚未在组件中对其进行更新。 / p>
与我一起忍受,因为下一篇文章并不会完全准确,但足以解释您所看到的内容。
Submit is clicked
-> Reset action is dispatched
-> Reducer receives action and returns updated state
-> Handle submit is fired using values prop (old state data still)
Component is updated with new props from redux state
如您所见,在我们的点击代码运行完毕之前,事件的顺序不允许向属性赋予更新状态。如果您曾经在JS Event Loop上观看过视频(强烈推荐),那么您会知道我们的onClick句柄将在其他任何异步操作(或点击后发生的同步操作)出现之前完全运行运行。
有充分的理由说明为什么没有立即为组件提供更新的道具,而主要的是性能。通过将handleSubmit包装在立即触发的异步事件中(实际上并不会立即触发,所有其他同步/异步操作在完成之前都已排队),您可以看到此顺序实际上是问题所在。
const resetAndSubmit = (event) => {
reset();
setImmediate(() => handleSubmit());
}
这将更改事件顺序,如下所示:
Submit is clicked
-> Reset action is dispatched
-> Reducer receives action and returns updated state
-> Handle submit is queued on the event loop (not run yet)
Component is updated with new props from redux state
Event loop reaches queued code and runs is
-> Handle submit is fired using values prop (new state data)
希望这可以帮助您了解出现问题的原因。至于解决它的解决方案。显然,您可以像上面显示的那样将句柄提交排队。您描述为使用分派执行提交的另一种选择。第三种选择是使用一些重的东西,例如redux-thunk或redux-sagas,它们将resetAndSubmit
动作绑定到一个调度中。坦白地说,这与选项二相同,只是简化为一次调度。选项四,不要对所有数据都使用redux。显然,这第四个选项带有折衷,但我的意思是,仅仅因为您在项目中使用redux并不意味着每个数据都需要在redux中。尽管它完全违背了redux形式的目的。
我还要补充一点,您并不孤单。当您介绍redux时,它会与您传统上考虑使用代码的方式混淆。通常,您认为我先执行A,然后执行B。但是使用redux时,您执行A,等待A的更改使其通过系统,然后执行B。这就是Sagas或Thunks很好的地方。您可以将更多的逻辑转移到商店来执行分派,而不是等待它全部通过props回到组件。