我有一个列表,我希望每次 ajax 请求获取一页数据后,将新的一页数据追加到列表当中。
在组件挂载时,我希望读取第一页的内容。简化后的代码可以写成这样:
import {useEffect, useState} from "react"; interface User { id: number name: string } const pageData = [ {id: 1, name: '张三'}, ] export default function App() { const [users, setUsers] = useState<User[]>([]) const fetchUsers = async () => { const page = pageData // 异步获取到数据 setUsers([...users, ...page]) } useEffect(() => { fetchUsers() // 发送异步请求 }, []) // 渲染列表 return ( <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> ) } 这样不会有任何问题。
但是今天我问 ChatGPT 的时候,他给了我这么个回答。

我觉得有点道理。所以我就在想,我是往列表里追加数据,那肯定是依赖于前一个状态的。因此我就把代码从
setUsers([...users, ...page]) 改成了
setUsers(prevUsers=>[...prevUsers, ...page]) 完整代码 :
import {useEffect, useState} from "react"; interface User { id: number name: string } const pageData = [ {id: 1, name: '张三'}, ] export default function App() { const [users, setUsers] = useState<User[]>([]) const fetchUsers = async () => { const page = pageData // 异步获取到数据 setUsers(prevUsers=>[...prevUsers, ...page]) } useEffect(() => { fetchUsers() // 发送异步请求 }, []) // 渲染列表 return ( <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> ) } 但这时候就出现了报错:

列表的数据追加了两次,key 也重复了。
我立马想到 React 的严格模式,果然关闭了,就又正常了:

到目前为止,我确实可以简单地
- 把 useState 改回去
- 关闭严格模式
以解决这个问题。
但是我觉得使用函数式的 setState 其实并没有太大问题,而 React 的严格模式又是官方推荐的。这俩者结合到一起,咋就出问题了呢?望大佬指点,是不是我使用的方式有问题。
