Quiero mostrar el mensaje "calculando..." durante un cálculo sincrónico pesado en el método del componente React.
Aquí está mi código.
Pero no funciona. Quiero que React llame a render() tanto después del primer setState como del segundo setState.
Pero React lo llama solo después del segundo setState.
¿Cómo puedo cambiar this.state.calculating correctamente?
// note: this is not async function function myHeavyFunc() {...} class Foo extends React.Components { constructor(props) { super(props); this.state = {calculating: false} this.handleXX = this.handleXX.bind(this); } handleXX() { this.setState({calculating: true}, () => { // first setState new Promise((resolve, reject) => { const x = myHeavyFunc(); resolve(x); }).then(x => { this.setState({calculating: false}); // second setState }); }); } render() { const y = this.state.calculating? <p>calculating...</p> : ''; return ( <div> {y} <button onClick={this.handleXX}>start calc</button> </div> ); } }Después de terminar su cálculo, debe volver a establecer la variable de estado "calculando" en "falso" en lugar de "verdadero":
handleXX() { this.setState({calculating: true}, () => { // first setState new Promise((resolve, reject) => { const x = myHeavyFunc(); resolve(x); }).then(x => { this.setState({calculating: false}); // second setState }); }); }Esto se debe a que js es un solo hilo.
Solo en tal caso, puede usar setTimeout para dar un tiempo para actualizar la interfaz de usuario para mostrar "calculando..." y luego llamar a myHeavyFunc.
Una solución más general es usar startTrantision, que está disponible en React 18.
Webworker también puede resolver esto.