如何强制组件使用 React 中的钩子重新渲染?

新手上路,请多包涵

考虑下面的钩子示例

 import { useState } from 'react';

 function Example() {
 const [count, setCount] = useState(0);

 return (
 <div>
 <p>You clicked {count} times</p>
 <button onClick={() => setCount(count + 1)}>
 Click me
 </button>
 </div>
 );
 }

基本上我们使用 this.forceUpdate() 方法来强制组件在 React 类组件中立即重新渲染,如下例所示

 class Test extends Component{
 constructor(props){
 super(props);
 this.state = {
 count:0,
 count2: 100
 }
 this.setCount = this.setCount.bind(this);//how can I do this with hooks in functional component
 }
 setCount(){
 let count = this.state.count;
 count = count+1;
 let count2 = this.state.count2;
 count2 = count2+1;
 this.setState({count});
 this.forceUpdate();
 //before below setState the component will re-render immediately when this.forceUpdate() is called
 this.setState({count2: count
 }

 render(){
 return (<div>
 <span>Count: {this.state.count}></span>.
 <button onClick={this.setCount}></button>
 </div>
 }
 }

但是我的问题是如何强制上面的功能组件立即用钩子重新渲染?

原文由 Hemadri Dasari 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.9k
2 个回答

这可以通过 useStateuseReducer ,因为 useState 在内部使用 useReducer

 const [, updateState] = React.useState();
 const forceUpdate = React.useCallback(() => updateState({}), []);

forceUpdate 不打算在正常情况下使用,仅用于测试或其他未解决的情况。这种情况可以以更传统的方式解决。

setCount 是不当使用 forceUpdate 的一个示例, setState 出于性能原因是异步的,不应仅仅因为状态更新未正确执行而强制同步。如果一个状态依赖于先前设置的状态,这应该使用 更新函数 来完成,

如果您需要根据之前的状态设置状态,请阅读下面的 updater 参数。

<…>

updater 函数接收到的 state 和 props 都是有保证的

是最新的。更新器的输出与

状态。

setCount 可能不是一个说明性示例,因为它的目的尚不清楚,但更新程序函数就是这种情况:

 setCount(){
 this.setState(({count}) => ({ count: count + 1 }));
 this.setState(({count2}) => ({ count2: count + 1 }));
 this.setState(({count}) => ({ count2: count + 1 }));
 }

这被 1:1 转换为钩子,但用作回调的函数应该更好地被记忆:

 const [state, setState] = useState({ count: 0, count2: 100 });

 const setCount = useCallback(() => {
 setState(({count}) => ({ count: count + 1 }));
 setState(({count2}) => ({ count2: count + 1 }));
 setState(({count}) => ({ count2: count + 1 }));
 }, []);

原文由 Estus Flask 发布,翻译遵循 CC BY-SA 4.0 许可协议

我正在使用一个数组并发现了这个问题。但是,我找到了另一种方法,而不是显式 forceUpdate - 解构数组并使用以下代码为其设置新值:

 setRoutes(arr => [...arr, newRoute]); // add new elements to the array
 setRouteErrors(routeErrs => [...routeErrs]); // the array elements were changed

我发现非常有趣的是,即使设置数组的副本也不会触发钩子。我假设 React 进行了浅层比较

原文由 ryzhman 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题