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的末尾,而不是停留在原处。
答案 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');