一般情况下,State 更新是异步更新 dom 的,比如下边这个例子
1import { useState, useRef } from 'react';
2import { flushSync } from 'react-dom';
3
4export default function TodoList() {
5 const [todos, setTodos] = useState(
6 Array(3).fill('').map((_, index) => ({
7 id: `${index + 1}`,
8 name: `todo_${index + 1}`
9 }))
10 );
11
12 function handleAdd() {
13 setTodos(todos => [ ...todos, {
14 id: `${todos.length + 1}`,
15 name: `todo_${todos.length + 1}`,
16 }]);
17
18
19 const input = document.getElementById(`${todos.length + 1}`);
20 console.log(' --input--', input);
21 }
22
23 return (
24 <>
25 <button onClick={handleAdd}>
26 Add
27 </button>
28 <div>
29 {todos.map(item => {
30 const { name, id } = item;
31 return (
32 <div key={id}>
33 <input id={id} value={id} />
34 {name}
35 </div>
36 )
37 })}
38 </div>
39 </>
40 );
41}
这时候可以使用 react-dom 提供的 flushSync,使得同步更新 dom:
1import { useState, useRef } from 'react';
2import { flushSync } from 'react-dom';
3
4export default function TodoList() {
5 const [todos, setTodos] = useState(
6 Array(3).fill('').map((_, index) => ({
7 id: `${index + 1}`,
8 name: `todo_${index + 1}`
9 }))
10 );
11
12 function handleAdd() {
13
14 flushSync(() => {
15 setTodos(todos => [ ...todos, {
16 id: `${todos.length + 1}`,
17 name: `todo_${todos.length + 1}`,
18 }]);
19 });
20
21 const input = document.getElementById(`${todos.length + 1}`)
22 console.log(' --input--', input.value)
23 }
24
25 return (
26 <>
27 <button onClick={handleAdd}>
28 Add
29 </button>
30 <div>
31 {todos.map(item => {
32 const { name, id } = item;
33 return (
34 <div key={id}>
35 <input id={id} value={id} />
36 {name}
37 </div>
38 )
39 })}
40 </div>
41 </>
42 );
43}
但会有一个点:虽然调用 flushSync 同步更新 dom,但是组件的 state 更新仍然是异步的;
1const [todos, setTodos] = useState(
2 Array(3).fill('').map((_, index) => ({
3 id: `${index + 1}`,
4 name: `todo_${index + 1}`
5 }))
6 );
7
8 function handleAdd() {
9 flushSync(() => {
10 setTodos(todos => [ ...todos, {
11 id: `${todos.length + 1}`,
12 name: `todo_${todos.length + 1}`,
13 }]);
14 });
15 const input = document.getElementById(`${todos.length + 1}`)
16 console.log(' --input--', input.value);
17
18
19 console.log('todos: ', todos);
20 }
个人笔记记录 2021 ~ 2025