Иногда вы терпите неудачу в ситуации, когда вы хотите повторно отрендерить компонент в состояние. Обычно это не очень хорошая практика, но все же есть способы добиться этого. Перехватчики React поддерживали только >16.8 версии.

Рассматривая ниже пример крючков

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

Теперь подходим к решению:

Это возможно с useState или useReducer, поскольку useState использует useReducer внутри:

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

forceUpdate не предназначен для использования при нормальных обстоятельствах, только для тестирования или других неурегулированных случаев. Эту ситуацию можно разрешить более традиционным способом.

setCount - пример неправильно используемого forceUpdate, setState является асинхронным по соображениям производительности и не должен быть синхронным только потому, что обновления состояния не были выполнены правильно. Если состояние зависит от ранее установленного состояния, это должно быть сделано с помощью функции обновления,

Если вам нужно установить состояние на основе предыдущего состояния, ознакомьтесь с аргументом средства обновления ниже.

<…>

Как состояние, так и свойства, полученные функцией обновления, гарантированно актуальны. Вывод средства обновления неглубоко объединяется с состоянием.

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

useCallback мемоизирует forceUpdate, поэтому он остается постоянным в течение срока службы компонента и может безопасно передаваться в качестве опоры. updateState({}) обновляет состояние новым объектом при каждом forceUpdate вызове, это приводит к повторному рендерингу. Так что да, он вызывает обновление при вызове.

Надеюсь, вам понравилось решение.

Будьте в курсе ❤