初学React:请求数据参数未更新 && 数据异步状态更新问题

javascript 复制代码
 // 请求参数
const [params, setParams] = useState({
    page: 1,
    per_page: 4,
    begin_pubdate: null,
    end_pubdate: null,
    status: '',
    channel_id: null
  })
  // 点击按钮
 const onFinish = (formValue)=>{
    // 设置参数
    setParams({
      ...params,
      channel_id:formValue.channel_id,
      status: formValue.status,
      begin_pubdate: formValue.date ? formValue.date[0].format('YYYY-MM-DD') : null,
      end_pubdate:  formValue.date ? formValue.date[1].format('YYYY-MM-DD')  :  null
    })
  // 更新表格数据
    getTableList()
  }

首次点击按钮导致请求参数没有更新问题。

原因在于 React 的状态更新是异步的。在 onFinish 函数中,先调用了 setParams 更新筛选参数,然后立即调用 getTableList。但由于 setParams 不会立即修改 params 的值,此时 getTableList 内部读取的仍然是旧的 params,因此第一次请求没有带上新选择的筛选条件。第二次点击时,params 已经更新为上一次的值,所以请求能带上上次的条件,但这次又可能因为同样的原因滞后。

解决方案

1. 在 onFinish 中构造新参数并直接传给 getTableList(推荐)

修改 getTableList 使其接受参数,调用时传入最新的筛选条件。

javascript 复制代码
// 修改 getTableList,增加参数
const getTableList = async (reqParams) => {
  // 如果没有传入参数,则使用当前 state 中的 params(用于首次加载)
  const finalParams = reqParams || params;
  try {
    const res = await http.get('/mp/articles', { params: finalParams });
    const { results, total_count } = res.data;
    setArticleTableList({
      list: results,
      count: total_count
    });
  } catch (error) {
    console.log(error);
  }
};

// 修改 onFinish
const onFinish = (formValue) => {
  // 基于当前 params 和表单值构造新参数对象
  const newParams = {
    ...params,
    channel_id: formValue.channel_id,
    status: formValue.status,
    begin_pubdate: formValue.date ? formValue.date[0].format('YYYY-MM-DD') : null,
    end_pubdate: formValue.date ? formValue.date[1].format('YYYY-MM-DD') : null
  };
  setParams(newParams);          // 更新状态用于后续操作(如分页)
  getTableList(newParams);       // 立即用新参数请求数据
};

2. 使用 useEffect 监听 params 变化自动请求

删除 onFinish 中手动调用 getTableList 的代码,改为依赖 params 的副作用。

javascript 复制代码
useEffect(() => {
  getTableList();
}, [params]); // params 变化时重新请求

const onFinish = (formValue) => {
  setParams({
    ...params,
    channel_id: formValue.channel_id,
    status: formValue.status,
    begin_pubdate: formValue.date ? formValue.date[0].format('YYYY-MM-DD') : null,
    end_pubdate: formValue.date ? formValue.date[1].format('YYYY-MM-DD') : null
  });
  // 不需要再手动调用 getTableList
};

注意:使用 useEffect 时需要确保 params 的引用变化(每次更新都创建新对象),并且首次加载也会触发,因此初始 useEffect 中的手动调用可以移除。

总结

两种方式均可解决问题。第一种更直观,请求时机完全由开发者控制;第二种更符合 React 数据流,但需注意避免额外副作用。根据你的场景选择即可。

相关推荐
光影少年3 分钟前
Redux Toolkit 用法、解决原生Redux 冗余问题
开发语言·前端·javascript·react.js·中间件·前端框架·ecmascript
whuhewei1 小时前
一道React缓存的题目
javascript·react.js
GISer_Jing21 小时前
前端沙箱开源项目推荐(React/Next/Vue优先)
前端·react.js·开源
暗不需求1 天前
React 性能优化秘籍:深入理解 `useMemo` 与 `useCallback`
前端·react.js·面试
向上的车轮1 天前
React 19 快速入门:拥抱服务端组件与新特性的现代化开发
前端·javascript·react.js
kyriewen2 天前
14MB VS 15KB:前React核心成员用AI写了个排版库,让Safari快了一千倍
前端·javascript·react.js
qcx232 天前
【系统学AI】07 ReAct范式:从奠基之作到Reflexion/RAF的演进
前端·人工智能·react.js
米丘2 天前
React19.x 一个示例来看 Diff 算法
javascript·react.js
喵了几个咪2 天前
吃透后台权限系统:从架构设计到 Vue3/React 双框架完整落地
前端·vue.js·react.js·权限系统
Aerfajj2 天前
React18的边学边记
前端·react.js