考虑下面的钩子示例

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

但我的问题是,我如何才能强制上述功能组件重新渲染立即与挂钩?


当前回答

这将渲染依赖组件3次(具有相等元素的数组是不相等的):

const [msg, setMsg] = useState([""])

setMsg(["test"])
setMsg(["test"])
setMsg(["test"])

其他回答

这可以通过useState或useReducer实现,因为useState在内部使用useReducer:

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

forceUpdate不打算在正常情况下使用,只能在测试或其他突出的情况下使用。这种情况可以用更常规的方法来解决。

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

如果需要基于前面的状态设置状态,请阅读下面的updater参数。 <…> updater函数接收的状态和道具都是有保证的 与时俱进。与更新程序的输出进行浅合并 状态。

setCount可能不是一个说明性的例子,因为它的目的不清楚,但这是updater函数的情况:

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 }));
   }, []);

你最好只让你的组件依赖于状态和道具,它会像预期的那样工作,但如果你真的需要一个函数来强制组件重新呈现,你可以使用useState钩子,并在需要时调用这个函数。

例子

const { useState, useEffect } = React; 函数 Foo() { const [, forceUpdate] = useState(); useEffect(() => { setTimeout(forceUpdate, 2000); }, []); 返回 <div>{Date.now()}</div>; } ReactDOM.render(<Foo />, document.getElementById(“root”)); <script src=“https://unpkg.com/react@16.7.0-alpha.0/umd/react.production.min.js”></script> <script src=“https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.production.min.js”></script> <div id=“root”></div>

潜在的选项是仅在特定组件上使用键强制更新。更新键会触发组件的呈现(之前更新失败)

例如:

const [tableKey, setTableKey] = useState(1);
...

useEffect(() => {
    ...
    setTableKey(tableKey + 1);
}, [tableData]);

...
<DataTable
    key={tableKey}
    data={tableData}/>

在Hook中有许多强制重渲染的方法。

对我来说,使用useState()和引用对象值提示的简单方法。

const [, forceRender] = useState({});

// Anywhre
forceRender({});

Codesandbox例子

我在使用一个数组时发现了这个问题。然而,我发现了另一种方法,而不是显式的forceUpdate——解构一个数组,并使用下面的代码为它设置一个新值:

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

我发现非常有趣的是,即使设置一个数组的副本也不会触发钩子。我认为React只做了浅层的比较