useSelector 钩子和重新渲染

Posted

技术标签:

【中文标题】useSelector 钩子和重新渲染【英文标题】:useSelector hook and rerenders 【发布时间】:2020-06-27 16:18:54 【问题描述】:

-- 编辑 -- 我创建了一个代码框:https://codesandbox.io/s/xenodochial-hofstadter-d3jjo

我开始摸不着头脑,希望得到一些帮助——我想——一个简单的问题。

我有一个基本的 App 组件,它呈现受控文本输入。一旦你提交了这个输入,它就会在后端创建一条消息,更新一个 redux 存储。这部分似乎一切正常。

我的问题是当我尝试添加 useEffect 挂钩以在添加新消息后重置输入值时。我注意到依赖于[messages]useEffect 在每次渲染时都会被调用,而不是仅在messages 更改时调用。输入输入的简单动作 - 导致每个字符重新呈现 - 触发钩子,即使它仍然是相同的值:一个空数组。

基本上,我注意到它只有在我的 useSelector 返回相同的数组实例时才能按预期工作。因此,如果我只阅读 state.messages.allIds 它会起作用,因为数组不会改变。但是只需添加一个.map(x => x) 就可以让它每次都返回一个新实例。 我已经添加了 react-redux 的 shallowEqual 来尝试解决这个问题,但无济于事,我不明白为什么它不能解决我的问题。

const App = () => 
  const [message, setMessage] = useState('');
  const messages = useSelector(
    (state: RootState) => (
      state.messages.allIds.map((id: string) => state.messages.byId[id])
    ),
    shallowEqual,
  );

  useEffect(() => 
    console.log('useEffect');
  , [messages]);

  // ...

  return (
    <form onSubmit=/* ... */>
      <input
        onChange=event => setMessage(event.target.value)
        value=message
      />
    </form>
  );

【问题讨论】:

【参考方案1】:

这可能来得很晚。但它可能会使面临同样问题的其他人受益。

如果您不希望函数在状态更改时重新渲染,而只想提取 redux 状态变量的值,则可以使用 useState

const state = useState();
const yourVariable = state.getState().reduxStateVariable;

【讨论】:

它是 useStore(),而不是 useState().. useState 钩子(通常)是来自基本 React 包的钩子。 Redux 有 useStore 钩子。

以上是关于useSelector 钩子和重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

使用自定义挂钩时的重新渲染问题

React:我想提交一个表单并想通过钩子(useSelector和useDispatch)将数据保存在redux store中

在我的权限上下文提供程序的函数错误中调用了 React 钩子“useSelector”

如何正确使用带有 react-redux 的 useSelector 钩子的 curried 选择器函数?

尽管状态发生了变化,但自定义钩子不会触发组件重新渲染

如何在初始渲染后重新渲染自定义钩子