【发布时间】:2020-12-14 06:01:20
【问题描述】:
我正在学习redux,想了解useSelector如何更新组件,因为组件没有自己的状态。
我了解useSelector()将组件订阅到商店,当商店更新时,组件也会更新。
类组件有this.forceUpdate(),但函数式组件没有。
如何强制更新功能组件?
【问题讨论】:
-
如果 useSelector 没有更新组件,你可能改变了 reducer 中的状态。
我正在学习redux,想了解useSelector如何更新组件,因为组件没有自己的状态。
我了解useSelector()将组件订阅到商店,当商店更新时,组件也会更新。
类组件有this.forceUpdate(),但函数式组件没有。
如何强制更新功能组件?
【问题讨论】:
你可以这样做
添加一个可以更改的虚拟状态以可靠地启动重新渲染。
const [rerender, setRerender] = useState(false);
...
//And whenever you want to re-render, you can do this
setRerender(!rerender);
这将重新渲染组件,因为组件总是在状态更改时重新渲染
【讨论】:
首先,我想提一下,当你使用 useSelector 钩子时,你不需要强制更新。每当更新选定的状态值时,都会自动进行重新渲染。
但是如果你需要强制更新功能组件你可以使用这种方法。
import React, { useState } from 'react';
//create your forceUpdate hook
function useForceUpdate(){
const [value, setValue] = useState(0); // integer state
return () => setValue(value => ++value); // update the state to force render
}
function MyComponent() {
// call your hook here
const forceUpdate = useForceUpdate();
return (
<div>
{/*Clicking on the button will force to re-render like force update does */}
<button onClick={forceUpdate}>
Click to re-render
</button>
</div>
);
}
我强烈建议避免使用此 hack,在 99% 的问题中,您无需强制更新即可解决它们。但无论如何,很高兴知道在功能组件中也存在这种可能性。
【讨论】:
也许这样的事情可以帮助你:
在类组件中,您可以传递如下所示的属性...
<Element onSomethingHappen={
()=>{
if(shouldComponentUpdate())
this.forceUpdate();
}}/>
在函数组件中你可以像这样调用更新器:
function FunctionComponent(props){
//When you need it you can update like this one...
props.onSomethingHappen();
// Here you are ;) let me know if this helps you
}
【讨论】:
react-redux 包依赖于react/react-dom 的渲染引擎来触发使用useSelector 钩子的给定组件的重新渲染。
如果您查看useSelector 的source,您会注意到useReducer 的使用:
const [, forceRender] = useReducer((s) => s + 1, 0)
顾名思义 (forceRender),redux 使用它通过 react 触发重新渲染。
随着 v8 或 react-redux 的实现,此机制的实现发生了变化,但仍依赖于 react-hooks 进行重新渲染。
如果您对 React 如何处理重新渲染感到好奇,请查看 this excellent SO answer。它提供了有关 react-hooks 如何与调用组件相关联的实现细节的一个很好的入口。
我在这里不再重复 Ryan,而是总结一下:
渲染器保留对当前渲染组件的引用。在此渲染期间执行的所有钩子(无论它们嵌套在自定义钩子中的深度如何)最终都属于该组件。
因此,useReducer 与您在其中调用useSelector 的组件相关联。
useReducer 的 dispatch 函数会触发该组件的重新渲染(React 要么调用类组件的 render() 方法,要么执行功能组件的函数体)。
如果您想知道react-redux 如何确定何时应该强制重新渲染(通过使用useReducer),请再看看useSelector 的source code。
Redux 使用订阅者模式来获得状态更新的通知。如果 redux 的根状态被更新,会发生以下事情:
useSelector 应用程序中的钩子重新运行它们的选择器功能===比较)。 useSelector 的第二个参数可以是一个比较函数来改变这种行为
useReducer 挂钩触发重新渲染。订阅者模式非常类似于反应,但可能有助于节省许多重新渲染。与重新渲染相比,调用多个 useSelector 钩子成本更低。
【讨论】: