React父组件state更新后子Hooks组件未触发重渲染问题
问题根因
子组件不刷新根本不是父子传值的问题,是你更新state的方式踩了React的核心规则:
- 你用
splice直接删除原数组里的元素,这个方法会直接修改原数组本身,不会生成新数组 - 删完你传给
setTableData的还是原来那个数组的引用,React做浅对比的时候发现数组内存地址没变,直接判定状态没有更新,不会触发组件重渲染,子组件自然拿不到删除后的新数据。
另外你拿map遍历做删除逻辑也没必要,map是用来做数组映射返回新结构的,做条件筛选直接用filter更简洁。
修复方案
核心只需要修改父组件的deleteRowData方法即可,子组件的渲染逻辑本身没有问题,可以顺手删掉子组件里没用到的useEffect、冗余的react导入,减少无效代码。
修正后的父组件代码:
import React, { useState, useEffect } from "react"; import { Table } from "./components/Table.js"; import "./App.css"; function App() { const [tableData, setTableData] = useState([]); useEffect(() => { fetch("https://jsonplaceholder.typicode.com/posts") .then(response => response.json()) .then(data => setTableData(data)) }, []) const deleteRowData = (id) => { // filter会返回过滤后的全新数组,引用地址变化会被React检测到,自动触发重渲染 const updatedData = tableData.filter(row => row.id !== id); setTableData(updatedData); } return ( <div className="App"> <div className="container py-4"> <Table tableData={tableData} deleteRowData={deleteRowData} /> </div> </div> ); } export default App;
清理冗余后的子组件代码:
export const Table = (props) => { return ( <div> <table> <thead> <tr> <td>ID</td> <td>Title</td> <td>Edit</td> <td>Delete</td> </tr> </thead> <tbody> {props.tableData.map((row) => ( <tr key={row.id}> <td>{row.id}</td> <td>{row.title}</td> <td>Edit</td> <td onClick={() => props.deleteRowData(row.id)}>Delete</td> </tr> ))} </tbody> </table> </div> ) }
注意点
React状态更新必须遵守不可变原则:
- 原始类型(字符串、数字、布尔值)直接赋值就会生成新值,不会有这类问题
- 引用类型(数组、对象)不能直接修改原属性、原元素,必须生成一个全新的数组/对象传给set方法,React才能检测到状态变化,触发组件重渲染。
内容的提问来源于stack exchange,提问作者Supriya Kumari
相关产品推荐
相关产品推荐

