React useRef值更新后子组件未获取最新值问题排查
问题根因
你的代码存在3个核心问题,导致ref更新后子组件拿不到预期值:
useRef本身的特性是更新.current属性不会触发组件重渲染,但这不是你当前场景的核心问题:你试图在同一次map遍历的子组件渲染过程中修改ref值,让后续遍历的子组件拿到新值,但React的渲染流程不保证遍历执行顺序(并发渲染模式下遍历可能被打断、重放、调整顺序),渲染过程中修改外部状态(包括ref的current)本身就是违反React纯渲染要求的写法,会直接导致状态不一致。- 子组件的
forwardRef写法完全错误:你写的React.forwardref存在拼写错误(正确API名是React.forwardRef),且没有按照API要求传入渲染函数,子组件根本拿不到你传入的ref值。 - 逐小时AM/PM的计算逻辑存在设计缺陷:靠渲染过程中触发回调改共享ref的方式,只能处理一次AM/PM切换,如果展示的卡片超过12小时(比如展示24小时预报会切换两次AM/PM),逻辑会直接错乱,且每个卡片独立基于初始时间计算偏移,没有统一的时间基准。
修复方案
不要用ref存跨组件共享的时段状态,也不要在子组件渲染过程中修改父组件状态,直接在父组件遍历阶段提前算好每个卡片对应的小时、AM/PM标识,把计算完成的结果传给子组件即可,这是最稳定、最符合React设计规范的写法:
修复后的父组件代码(index.js)
import type { NextPage } from 'next' import WeatherCard from '../components/WeatherCard' import { motion } from 'framer-motion' import { useState } from 'react' import { PropsType } from '../types' const Home: NextPage<PropsType> = (props) => { const [time,setTime] = useState(new Date()); // 提前计算所有卡片所需数据,不在子组件渲染阶段修改共享状态 const cardList = determineWeatherCardsArr().map((el, index) => { // 计算当前卡片对应的准确时间 const cardTime = new Date(time.getTime() + index * 60 * 60 * 1000); // 直接调用原生API获取12小时制的小时和AM/PM,不需要手动维护切换逻辑 const [hour, ampm] = cardTime.toLocaleString('en-US', { hour: 'numeric', hour12: true }).split(' '); return { ...el, cardTitle: `${hour}${ampm}` } }) return ( <div> <main> {cardList.map((el,index) => ( <motion.div key={index}> <WeatherCard weather={el.weather} temp={el.temp} cardTitle={el.cardTitle} /> </motion.div> ))} </main> </div> ) } export default Home
修复后的子组件代码(WeatherCard.js)
不需要使用forwardRef,直接接收父组件计算好的props即可:
import Image from "next/image"; const WeatherCard = (props) => { return( <div className=""> <h3 className="">{props.cardTitle}</h3> </div> ) } export default WeatherCard
如果你坚持要用ref实现,需要先修正forwardRef的写法,同时把ref更新逻辑放到
useEffect中执行,更新ref后还要触发一次父组件重渲染才能让子组件拿到新值,但这种写法依然存在渲染顺序导致的状态不稳定问题,不推荐使用。
内容的提问来源于stack exchange,提问作者H.b
相关产品推荐
相关产品推荐

