javascript - 将 queryParameters 与 Redux 状态同步并为功能组件做出反应路由器
问题描述
我正在寻找集成以下堆栈的最佳实践
- 反应功能组件
- 还原状态
- 从 URL 查询参数
基本上,我有一个带有复杂过滤器组件的搜索页面,该组件负责处理页面上的过滤可能性。这些过滤器由下拉列表和复选框组成。如果选择/取消选择过滤器,我会通过操作/事件调度程序/reducer 等保持它们的状态。一旦单击按钮提交,就会对 API 进行异步 HTTP 调用,这将在页面上显示适当的结果
目前一切都运行良好。
棘手的部分是我希望能够通过 URL 共享这些过滤后的搜索。我认为最好用查询参数更新 URL。如 /search?filter1=ok&filter2=true
一旦用户输入 URL,过滤器组件将读取查询参数并更新状态。但是状态如何根据用户的操作附加/删除 URL 查询参数呢?
我只是在寻找不太复杂的解决方案,如果可能的话,使用我当前依赖的能力(我应该使用钩子吗?)
我找到了各种解决方案,但主要基于容器组件,我试图通过钩子坚持使用功能组件。
提前感谢您的提示和想法。
安塞尔姆
解决方案
这个解决方案可能比你想要的更复杂,因为你已经有了代码,但这里是我如何在没有添加 2 路绑定和每个人似乎都喜欢这些问题的额外库的情况下解决了这个问题。
改变您的理念并将您的历史/网址视为您的过滤器状态,将允许您使用您喜欢的所有单向模式。使用 url 作为新的过滤器状态,附加效果将让您触发效果,例如将应用程序状态同步到 url、获取等。这使您的标准导航功能(例如链接、来回等)可以免费使用,因为它们将简单地通过效果进行过滤。假设您使用标准的 react-router/redux 堆栈,该模式可能看起来像这样,但可以适应使用您手头的任何东西。
const dispatch = useDispatch();
const location = useLocation();
const parse = (search) => {
// parse search parameters into your filter object applying defaults ect.
};
useEffect(async () => {
const filters = parse(location.search);
dispatch({ type: 'SEARCH_START', payload: filters }); // set spinner, filters, ect.
const response = await fetch(/* your url with your filters */);
const results = await response.json();
dispatch({ type: 'SEARCH_END', payload: results });
// return a disposer function with a fetch abort if you want.
}, [location.search]);
此效果将解析并分派您的搜索操作。请注意它是如何直接从 读取值location.search
、解析它们,然后将这些值传递给 redux 或您使用的任何状态管理以及获取的。
要处理您的过滤器更新逻辑,您的搜索操作只需要推送历史记录。这将为您提供单向流,使结果与 url 保持同步,并使 url 与用户过滤器保持同步。您不再直接更新过滤器,状态必须朝一个方向流动。
const useFilters = () => {
const serialize = (filters) => {
// exact opposite of parse. Remove default filter values or whatever you want here.
// return your new url.
};
const history = useHistory();
const filters = useSelector(selectFilters); // some way to find your already parsed filters so you can add to them.
return {
sortBy: (column) => history.push(serialize({ ...filters, sortBy: column })),
search: (query) => history.push(serialize({ ...filters, query })),
filterByShipping: (priority) => {} // ect,
filterByVendor: (vendor) => {} // blah blah
};
}
上面是一个钩子形式的过滤器 api 的例子。您可以使用useFilters()
返回函数来更改 url。然后会触发效果,解析 url,触发新的搜索,并保存解析后的过滤器值,您可以在其他组件中使用。
parse
andserialize
函数只是将查询字符串中的值转换为过滤器并返回。这可以像您需要的那样复杂或简单。如果您已经在使用查询字符串库,则可以在此处使用它。在我的项目中,他们通常会解析诸如“q”之类的短键以进行查询,并返回一个单声道类型的过滤器值,如果它们未定义,则它们具有排序顺序等默认值。stringify/serialize 会做相反的事情。它会使用过滤器,将它们转换为短键,删除空值和默认值,然后输出一个搜索 url 字符串,我可以将其用于任何 urls/hrefs/ect。
推荐阅读
- javascript - Safari 12 上忽略了 getUserMedia 约束
- python - 将数字添加到多维数组python
- c++ - 可以使用memcpy cpp函数在系统内存和gpu内存之间复制数据吗?
- c# - 如何在资源中使用外部 Canvas xaml
- c# - C# OpenXml 接受 .docx 中的所有修订
- jquery - 每次使用 jQuery 进行新的 ajax 调用时,如何显示“加载微调器”?
- c# - Azure Functions Runtime v1 EventGrid 订阅创建失败
- c# - Visual Studio 错误 正在构建的项目的处理器架构 msil 与处理器架构不匹配
- java - 未提供身份验证详细信息 REST API POST 请求
- javascript - 是否有验证器来检查运算符是否已被使用?