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

问题描述 投票:12回答:3

考虑下面的钩子示例

   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>
        }
 }

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

javascript reactjs react-native react-hooks
3个回答
7
投票

这可能与useStateuseReducer,因为useState内部使用useReducer

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

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

setCount是使用不当的forceUpdate的一个例子。由于性能原因,setState是异步的,因为状态更新没有正确执行,所以不应强制同步。如果一个州依赖于先前设定的状态,这应该用updater function完成,

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

<...>

更新程序功能接收的状态和道具都保证是最新的。 updater的输出与state轻微合并。

setCount可能不是一个说明性的例子,因为它的目的不明确但更新器功能的情况如下:

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

6
投票

您应该最好只让您的组件依赖于状态和道具,它将按预期工作,但如果您真的需要一个强制组件重新渲染的函数,您可以使用useState钩子并在需要时调用该函数。

const { useState, useEffect } = React;

function Foo() {
  const [, forceUpdate] = useState();

  useEffect(() => {
    setTimeout(forceUpdate, 2000);
  }, []);

  return <div>{Date.now()}</div>;
}

ReactDOM.render(<Foo />, document.getElementById("root"));
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>

<div id="root"></div>

3
投票

正如其他人提到的那样,useState的工作原理 - 这就是mobx-react-lite如何实现更新 - 你可以做类似的事情。

定义一个新钩子,useForceUpdate -

export function useForceUpdate() {
  const [, setTick] = useState(0);
  const update = () => {
    setTick(tick => tick + 1);
  })
  return update;
}

并在组件中使用它 -

const forceUpdate = useForceUpdate();
if (...) {
  forceUpdate(); // force re-render
}

https://github.com/mobxjs/mobx-react-lite/blob/master/src/utils.tshttps://github.com/mobxjs/mobx-react-lite/blob/master/src/useObserver.ts


0
投票

您可以像这样简单地定义useState:

const [, forceUpdate] = React.useState(0);

用法:forceUpdate(n => !n)

希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.