React子组件调用父组件方法后状态未更新表格不刷新问题
问题根因
React本身状态变更触发重渲染的逻辑没有问题,表格不刷新完全是代码逻辑错误导致的,核心问题有两个,附带一个易读性问题:
- 异步请求时序错误:子组件里发PUT更新请求之后,你没等请求执行完成就立刻调用了
getData拉取数据。这时候后端还没完成数据落库,GET请求拿到的就是修改前的旧数据,setAPIData写入的本身就是未更新的内容,表格自然不会有变化。你现在能看到getData的日志打印,只能说明函数被调用了,不能证明拿到的是新数据。 - 列表渲染缺少返回值:父组件里遍历
apiData的时候,箭头函数用大括号包裹了渲染逻辑,但没有写return返回JSX节点。这种写法map执行后返回的数组全是undefined,就算state更新成最新值,页面上也渲染不出任何内容。 - 易读性问题:你
axios.get的then回调参数也命名成了getData,和外层的请求函数重名,虽然不影响运行,但读代码时很容易混淆,建议改成res这类通用命名。
修复步骤
1. 调整子组件异步逻辑,等更新完成再拉数据
把handleClose改成异步函数,等PUT请求执行完成后再调用getData:
const ChildButton = ({getData, ...}) => { async function handleClose() { setOpen(false) // 等待更新请求完成、数据落库 await axios.put(`https://blah.mockapi.io/fakeData/${id}`, { // 你的更新参数 }) // 再拉取最新数据 getData() } return ( <Button onClick={handleClose}> Update </Button> ) } export default ChildButton;
2. 修正列表渲染的返回值
两种写法选一种即可,记得给列表项加唯一key属性:
// 写法1:大括号内显式return <Table.Body> {apiData.map((obj) => { return ( <Table.Row key={obj.id}> <Table.Cell>{obj.field1}</Table.Cell> <Table.Cell>{obj.field2}</Table.Cell> <Table.Cell> <ChildButton getData={getData} /> </Table.Cell> </Table.Row> ) })} </Table.Body> // 写法2:用小括号包裹JSX,隐式返回 <Table.Body> {apiData.map((obj) => ( <Table.Row key={obj.id}> <Table.Cell>{obj.field1}</Table.Cell> <Table.Cell>{obj.field2}</Table.Cell> <Table.Cell> <ChildButton getData={getData} /> </Table.Cell> </Table.Row> ))} </Table.Body>
3. 可选性能优化
如果后续要做渲染性能优化,可以用useCallback包裹父组件的getData方法,避免每次渲染都生成新的函数引用,导致子组件无效重渲染:
import { useState, useCallback } from 'react'; // 父组件内 const getData = useCallback(() => { axios.get(`https://blah.mockapi.io/fakeData`) .then((res) => { setAPIData(res.data); }) console.log('getData'); }, []);
改完以上核心问题后,点击更新按钮就能看到表格正常刷新最新数据了。
内容的提问来源于stack exchange,提问作者Austin Lelonek
相关产品推荐
相关产品推荐

