等待后,React Hooks将渲染多次

时间:2020-04-24 04:44:34

标签: reactjs react-hooks

const [ html, setHTML ] = useState('');
const [ script, setScript ] = useState('');

const update = (script, html) => {
  setScript(script);
  setHTML(html);
};

update('a', 'b'); // actual code in an event handler

上面的代码运行良好,React Hooks将渲染一次并结合setScript和setHTML;

const [ html, setHTML ] = useState('');
const [ script, setScript ] = useState('');

const update = async (script, html) => {
  await new Promise(resolve => setTimeout(resolve, 10));
  setScript(script);
  setHTML(html);
};

update('a', 'b'); // actual code in an event handler

上面的代码不再起作用,React Hooks将渲染TWICE,并且不会结合使用setScript和setHTML。

我可以将代码更改为:

const [ state, setState ] = useState({
  html: '',
  script: ''
});

const update = async (script, html) => {
  await new Promise(resolve => setTimeout(resolve, 10));
  setState({
    script,
    html
  });
};

update('a', 'b'); // actual code in an event handler

上面的代码仅呈现一次,但有一个新的错误:textArea中的光标(脚本和html所在的位置)将移动到textArea的末尾,而不是停留在原处。

1 个答案:

答案 0 :(得分:0)

这是不可避免的:当异步运行代码时,React无法知道在当前的setter之后可以执行更多的同步setter,因此它必须为每个触发器触发渲染。您可以像创建一个状态对象那样批处理,也可以使用unstable_batchedUpdates

import {unstable_batchedUpdates as batchedUpdates} from 'react-dom';

// ....

const [ html, setHTML ] = useState('');
const [ script, setScript ] = useState('');

const update = async (script, html) => {
  await new Promise(resolve => setTimeout(resolve, 10));
    batchedUpdates(() => {
        setScript(script);
        setHTML(html);
    });
};

update('a', 'b');