Иногда вы терпите неудачу в ситуации, когда вы хотите повторно отрендерить компонент в состояние. Обычно это не очень хорошая практика, но все же есть способы добиться этого. Перехватчики 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
вызове, это приводит к повторному рендерингу. Так что да, он вызывает обновление при вызове.
Надеюсь, вам понравилось решение.
Будьте в курсе ❤