反应路由导致输入失去焦点

时间:2020-04-09 04:24:46

标签: reactjs react-router

我有一个带有包含输入的组件的应用。当用户更改输入时,我想更新URL中的查询字符串以反映新状态。我通过检测当前location.search值和状态生成的查询字符串之间的差异来实现这一点。如果存在差异,我将返回一个<Redirect>组件,其中查询args反映了新状态。

问题在于,每次进行此类重定向后,组件都会重新渲染,而我的输入将被新的输入替换,这意味着我刚刚更改的输入不再存在,因此没有焦点。如果是文本输入,则每次按键后都会失去焦点。

我如何处理它是记住状态改变时具有焦点的元素的ID,然后在组件重新渲染后基于document.getElementById将焦点设置到新元素。

我已将问题简化为https://codesandbox.io/s/github/TrevorMills/react-routing-conundrum的最小应用程序。该问题同时出现在功能组件和React.Component类上。

我的机制对我来说似乎很棘手。我对外面的React专家的问题是,我错过了什么吗?是否有比<Redirect>更好的使状态进入位置查询参数的方法?我尝试将key添加到我的输入中,但没有任何区别。如果我的机制似乎合法,是否有办法将其整体以更高阶的组件应用于应用程序?

谢谢。

2 个答案:

答案 0 :(得分:3)

由于您使用了重定向,因此在每次更改输入值时,组件渲染都会在返回值和重定向之间切换,从而导致所有组件都重新安装而不是重新渲染。这将导致输入字段失去焦点。

避免使用<Redirect />,并在更新状态后使用history.replace

您可以像这样编写history.replace,而不是在onChangeText函数中执行useEffect

useEffect(() => {
    props.history.replace(props.location.pathname + "?" + qs.stringify(state));
  }, [state]);

更新的工作示例在这里:

https://codesandbox.io/s/cocky-swirles-kcqwo?file=/src/App.js

答案 1 :(得分:1)

我已经编辑了您的代码的功能组件版本,但是我所做的更改应同时适用于两者。

我做的主要事情是删除了状态重复。我没有复制从路由到组件的状态,而是使组件直接使用查询参数作为状态。然后,我使updateState函数使用props.history.replace更新查询参数,这是React Router允许命令式导航的方式。

希望这会有所帮助!

https://codesandbox.io/s/great-williamson-0pxyb