阅读视图

发现新文章,点击刷新页面。

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

 // 请求参数
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 使其接受参数,调用时传入最新的筛选条件。

// 修改 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 的副作用。

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 数据流,但需注意避免额外副作用。根据你的场景选择即可。

❌