使用Redux-Form搜索过滤器,如何“重置”并重新提交表单?

时间:2019-05-29 02:02:40

标签: javascript reactjs redux redux-form

更新:这是Pen的示例

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}
/>

我已经尝试了几件事,但这是最近的镜头:

我从默认道具中抢走resetchange和其他东西。我根据需要传递了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')); 

TL; DR和最后一个问题:

如何正确重置表单并提交其默认/空值?

每次我分发或直接调用Redux Form'submit'时,最终都会在之前提交表单,以清除状态或UI中的值。 我已经通过调试器进行了调试,并且不会跳过对resetchange的呼叫。这就像一个异步/竞赛问题,但是我承认在这种情况下,我肯定不属于我。

我只是直截了当地做错了吗?

1 个答案:

答案 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回到组件。