React Hooks setState更新后视图不刷新、useEffect循环报错问题求助
问题根因
- 状态更新采用了可变修改,引用未发生变化:
rentDrone方法中使用_.pull(station.drones, drone.model)直接修改了原station对象的drones数组,虽然通过map生成了新的updateStations数组,但数组内的station对象、以及station的drones属性引用和更新前完全一致。React状态更新采用浅比较检测变化,子组件Station的useEffect依赖drones属性,因为引用没变,所以检测不到更新,不会重新执行逻辑刷新内部的dronesList,最终UI无变化。 - 移除useEffect依赖触发无限循环的原因:如果不填写依赖数组,useEffect会在每次组件渲染后都执行,内部执行
setDronesList会触发组件重渲染,重渲染又会再次执行useEffect,形成死循环,因此报深度超限错误。
修复方案
1. 修正App组件的状态更新逻辑,采用不可变更新
修改rentDrone方法,更新stationsList时生成全新的station对象和drones数组,触发React的变更检测:
const rentDrone = (drone: IDrone) => { const updateStations = stationsList?.map((station) => { if (station.drones.includes(drone.model)) { // 生成新的drones数组,不修改原数组 const newDrones = station.drones.filter(model => model !== drone.model) // 返回全新的station对象,修改引用让React识别到变更 return { ...station, drones: newDrones } } else { return station } }); setStationsList(updateStations); setRental([ { drone: [drone], isReturning: false, }, ]); setIsLoading(false); };
2. 可选:简化Station组件逻辑,避免不必要的副作用和内部状态
你当前Station组件内的dronesList是纯同步计算的结果,不需要用useEffect和内部状态存储,直接在渲染时计算即可,从根源避免依赖问题:
import React, { FC } from "react"; import { Row } from "react-bootstrap"; import { Drone } from "../Drone/Drone"; import quadsFile from "../../assets/quads.json"; export const Station: FC<IStation> = ({ name, drones }) => { // 直接在渲染时计算对应站点的无人机列表 const dronesList = quadsFile.quads.filter((drone) => { return drones.includes(drone.model); }); return ( <Row className="mb-3"> <h2>{name}</h2> {dronesList.map((drone, i) => { return <Drone {...drone} key={i} />; })} </Row> ); };
3. 可选:优化列表key取值
当前渲染Station、Drone组件时使用数组索引作为key,如果后续列表顺序可能发生变化,建议替换为唯一业务标识(比如station的name、drone的model),避免渲染异常。
内容的提问来源于stack exchange,提问作者James Wilkinson
相关产品推荐
相关产品推荐

