javascript - 使用 Redux-Form 进行搜索过滤器,我如何才能 "reset"并重新提交表单?

标签 javascript reactjs redux redux-form

更新:这是一个例子

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() 运行并提交表单之前,表单和状态值不会更新。

我认为这可能与优先提交事件有关?

我也尝试过一些简陋的东西,比如导入change(容器的默认属性)并定义重置按钮:

<button
  name="reset_filters_button"
  type="button"
  onClick={() => {
    change('organization_name', '');
    methodThatDispatchesSubmitAction();
  }}
  disabled={pristine || submitting}
>
  Clear Search
</button>

哪个(如果我删除 methodThatDispatchesSubmitAction())可以正常工作以将字段值设置回空白,从而使表单在技术上也再次“原始”。

methodThatDispatchesSubmitAction() (如果不是很明显)通过 dispatchToProps 绑定(bind)到父级,并传递到表单容器,它使用“远程提交”建议,例如,

// organization_list_filter == name of the Redux-Form to submit. 
dispatch(submit('organization_list_filter')); 

TL;DR 和最后一个问题:

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

每次我分派(dispatch)或直接调用 Redux 表单“提交”时,它都会在 从状态或 UI 清除值之前提交表单。 我已经使用调试器完成了这个,它没有跳过我对 resetchange 的调用。这就像一个异步/竞争问题,但我承认在这个特殊情况下我肯定不在我的联盟中。

我是不是直接做错了?

最佳答案

这绝对是一个竞争条件问题(或者因为我们实际上不是在处理线程,所以是事件顺序问题)。

使用 methodThatDispatchesSubmitAction 的原因是当您当前的示例不起作用时,是因为分派(dispatch)的操作具有直接从 redux 存储读取数据的好处。您的示例不是从 redux 存储中读取,而是从传入的属性中读取。是的,此属性来自 redux 存储,但您看到的问题是它尚未在您的组件中更新。

请耐心等待,因为下一篇文章不会完全准确,但足以解释您所看到的内容。

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 事件循环的视频(我强烈推荐),您就会知道我们的 onClick 句柄将在任何其他异步操作(或我们点击后的同步操作)有机会之前完全运行运行。

组件没有立即获得更新的 props 是有充分理由的,但主要原因是性能。通过将 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 Action 绑定(bind)到一个单独的调度中。虽然老实说,这与选项二相同,只是简化为一次调度。选项四,不要对所有数据使用 redux。显然,这第四个选项需要权衡取舍,但我的观点是,仅仅因为你在项目中使用 redux 并不意味着每一个数据都需要在 redux 中。尽管它完全违背了 redux-forms 的目的。

我还应该补充一点,您并不是唯一对此感到困惑的人。当您引入 redux 时,它会扰乱您传统上使用代码的方式。通常你认为,我先做 A,然后做 B。但是对于 redux,你做 A,等待 A 的更改通过系统,然后你做 B。这就是 Sagas 或 Thunks 可以很好的地方。您将更多逻辑移至 store 以对调度进行操作,而不是等待它全部通过 props 返回到组件。

关于javascript - 使用 Redux-Form 进行搜索过滤器,我如何才能 "reset"并重新提交表单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56352136/

相关文章:

javascript - 替换类名在 jquery 中不起作用

javascript - 如果调整了一张卡片的大小,请连续调整所有卡片的大小

javascript - 初始化 react 组件状态

javascript - react + redux - 401 - 未经授权 - 请求 header 中缺少 header

reactjs - 全局 Redux 状态值

javascript - 在 MVC 中创建新 View 时,旧 View 会发生什么情况

javascript - 画廊的图像预加载器一张一张?这有什么问题吗?

javascript - 如何在 React useState 中存储和更新多个值?

javascript - 使用内联样式 ReactJS 根据滚动值旋转图像

javascript - 在刷新来自 firebase 的新数据之前清除 react 状态字段