React useState的两种赋值办法区别?

作者站长头像
站长
· 阅读数 20

感谢各位朋友进来观看,哪怕只是了解并未解惑。若闲代码多,小弟也可以略微解释一下。主要的问题就是:setPage后,useEffect能监听到page发生了变化。可在loadData函数内部使用时,拿到的还是未更改时的page值。

下面是具体代码:

import { useState, useEffect } from 'react'

export default function () {
  const [page, setPage] = useState({ current: 1, pageSize: 10 });
  function loadData() {
    console.log({ current: page.current })
  }

  useEffect(() => {
    console.log('发生了改变', page)
  }, [page])

  function onClick() {
    setPage((pre) => ({ ...pre, current: pre.current + 1 }))
    setTimeout(() => {
      console.log('加载数据时', page)
      loadData()
    }, 1000)
  }
  return <>
    <div>
      <p>测试页面</p>
      <button onClick={onClick}>添加</button>
    </div>
  </>
}

感谢各位朋友能完整的看完代码,若有看法或者其他都可以说出来,谢谢各位

回复
1个回答
avatar
test
2024-07-07

问题原因:函数组件里通过 useState 获取的 pageloadData 里的 page 形成一个闭包。点击按钮后,函数组件重新执行,此时 useState 返回的了一个新的 page,注意区分这个新 page 不是之前形成闭包的旧 page,而 loadDatapage 绑定的是旧的 page,所以你拿到的是未更改的值。

解决方案:将 setTimeout 这种带有副作用的函数放在 useEffect 中处理:

import { useState, useEffect } from "react";

export default function App() {
  const [page, setPage] = useState({ current: 1, pageSize: 10 });
  function loadData() {
    console.log({ current: page.current });
  }

  useEffect(() => {
    console.log("发生了改变", page);
  }, [page]);

// 带有副作用的函数放在 useEffect 处理
  useEffect(() => {
    const id = setTimeout(() => {
      console.log("加载数据时", page);
      loadData();
    }, 1000);
    return () => clearTimeout(id);
  }, [page]);

  function onClick() {
    setPage((pre) => ({ ...pre, current: pre.current + 1 }));
    // setTimeout(() => {
    //   console.log("加载数据时", page);
    //   loadData();
    // }, 1000);
  }
  return (
    <>
      <div>
        <p>测试页面</p>
        <button onClick={onClick}>添加</button>
      </div>
    </>
  );
}

这是 React 的经典闭包问题,回答的比较简略,希望对你有所帮助。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容