You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决React useEffect无限循环与添加数据后列表不刷新问题

解决React表单新增条目后列表不实时更新的问题

问题分析

你当前的核心矛盾是:

  • 给useEffect传空数组[]当依赖时,数据只在组件挂载时拉取一次,新增条目后不会主动重新请求,必须刷新页面才能看到新内容
  • 去掉useEffect的依赖项,会导致每次组件渲染都触发请求,而setData又会引发组件重新渲染,进而形成无限请求循环

解决方案

下面提供两种实用的解决方式,可根据你的业务场景选择:

方式一:新增成功后手动触发数据刷新

把获取数据的逻辑抽成独立函数,在onFinish的POST请求成功后直接调用,实现新增后立刻拉取最新数据更新列表。同时删除操作也可以复用这个逻辑,保证删除后列表也能实时更新。

修改后的完整代码:

function FieldSetting() {
  const [form] = Form.useForm()
  const [typeValue, setTypeValue] = useState()
  const meta = {
    fields: [{ key: "pathname", onChange: (e) => setTypeValue(e.target.value) }],
  }
  const [data, setData] = useState([])

  // 抽离获取数据的独立函数,方便复用
  const getData = async () => {
    try {
      const response = await fetch(`api?id=${typeId}`)
      const newData = await response.json()
      setData(newData)
    } catch (e) {
      console.log(e)
    }
  }

  async function onFinish() {
    try {
      await axios.post("api", { typeValue, typeId })
      form.resetFields()
      // 新增成功后立即拉取最新数据
      await getData()
    } catch (e) {
      console.log(e)
    }
  }

  // 组件挂载时初始化数据
  useEffect(() => {
    getData()
  }, [])

  return (
    <Container>
      <Form form={form} layout="inline" className="form-field" onFinish={onFinish}>
        <FormBuilder form={form} meta={meta} />
        <Form.Item>
          <Button type="primary" htmlType="submit">
            Add
          </Button>
        </Form.Item>
      </Form>
      <div
        id="scrollableDiv"
        style={{
          height: 665,
          overflow: "auto",
          padding: "0 16px",
          border: "1px solid rgba(140, 140, 140, 0.35)",
        }}
      >
        <List
          itemLayout="horizontal"
          dataSource={data}
          renderItem={(item) => (
            <List.Item
              actions={[
                <a key="list-edit">edit</a>,
                <a 
                  onClick={async () => {
                    try {
                      await axios.delete(`http://gage.axaneh.com/api/Gages/SettingProduct/RemoveProductSetting/${item.id}`)
                      // 删除成功后刷新列表
                      await getData()
                    } catch(e) {
                      console.log(e)
                    }
                  }} 
                  key="list-delete"
                >
                  delete
                </a>,
              ]}
            >
              <List.Item.Meta title={item.typeValue} />
            </List.Item>
          )}
        />
      </div>
    </Container>
  )
}

export default FieldSetting

方式二:优化useEffect依赖+处理竞态(适配typeId动态变化场景)

如果typeId是会动态改变的变量,可以把它加入useEffect的依赖数组,这样当typeId变化时自动重新拉取数据。同时用AbortController处理竞态问题(避免前一次请求还没完成,新请求就发起导致数据覆盖错误)。

核心修改部分:

useEffect(() => {
  const controller = new AbortController()
  const signal = controller.signal

  const getData = async () => {
    try {
      const response = await fetch(`api?id=${typeId}`, { signal })
      const newData = await response.json()
      setData(newData)
    } catch (e) {
      // 忽略请求被取消的错误
      if (e.name !== 'AbortError') {
        console.log(e)
      }
    }
  }

  getData()

  // 组件卸载或依赖变化时取消未完成的请求
  return () => controller.abort()
}, [typeId]) // 依赖typeId,值变化时自动重新请求

async function onFinish() {
  try {
    await axios.post("api", { typeValue, typeId })
    form.resetFields()
    // 如果typeId没变化,这里仍需手动调用getData刷新数据
    await getData()
  } catch (e) {
    console.log(e)
  }
}

额外优化:乐观更新(提升用户体验)

如果想让用户立刻看到新增的条目(不用等请求返回),可以采用乐观更新:先把新条目加入本地列表,请求成功就保留真实数据,失败则回滚。示例:

async function onFinish() {
  // 创建临时条目用时间戳当临时id
  const tempItem = { typeValue, id: Date.now() }
  // 先更新本地列表
  setData(prev => [...prev, tempItem])

  try {
    const response = await axios.post("api", { typeValue, typeId })
    const newItem = response.data // 假设后端返回完整的新条目数据
    // 替换临时条目为真实数据
    setData(prev => prev.map(item => item.id === tempItem.id ? newItem : item))
    form.resetFields()
  } catch (e) {
    console.log(e)
    // 请求失败,回滚本地数据
    setData(prev => prev.filter(item => item.id !== tempItem.id))
  }
}

内容的提问来源于stack exchange,提问作者Andish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 09:45:35