Next.js中React子组件Props不更新问题排查与解决
React/Next.js中父组件state更新后子组件props未同步的问题解决
我在实现窗口resize时更新父组件state并传递给子组件,但子组件仅在初始加载时接收到props,后续resize时完全不更新。不管是直接用事件监听器还是通过useEffect绑定,结果都一致。
初始问题代码
父组件代码
const [innerWidthProp, setInnerWidthProp] = useState<number>(0); useEffect(() => { window.onresize = () => { setInnerWidthProp(window.innerWidth) console.log(innerWidthProp) // 窗口 resize 时打印宽度 } }, [innerWidthProp, setInnerWidthProp]) return ( <div className='header-container'> <NavLinks title={'SOLDIER'} scrollValue={innerWidthProp} onLinkClick={onLinkClick} /> </div> )
子组件代码
console.log(props.scrollValue) // 仅在加载时打印宽度,resize 时不更新
一开始怀疑是Next.js的问题(测试计数器也只有父组件更新),后来发现根源:state变量和useCallback引用的函数分别位于不同层级的父组件中,导致props传递链路断裂。
修复后可正常运行的代码
parent.tsx(最外层父组件,统一管理state)
const Main: NextPage<GithubProps> = ({githubAccountData, githubSubscribe}) => { const [innerWidthProp, setInnerWidthProp] = useState<number>(); const updateWidth = () => setInnerWidthProp(window.innerWidth) useEffect(() => { window.addEventListener('resize', updateWidth) console.log(innerWidthProp) updateWidth() // 初始化时主动获取一次窗口宽度 return () => window.removeEventListener('resize', updateWidth) }, [innerWidthProp, setInnerWidthProp]) const handleLinkClick = (props: number) => { console.log(props) window.scrollTo(props, 0) } return ( <div> {/* 将state和回调传递给中间层子组件 */} <Header innerWidthProp={innerWidthProp} onLinkClick={handleLinkClick} /> </div> ) }
firstchild.tsx(中间层组件,转发props)
const Header: FunctionComponent<LinkProps> = ({ onLinkClick, innerWidthProp }): JSX.Element => { return ( <div className='header-container'> <NavLinks title={'SOLDIER'} scrollValue={0} onLinkClick={onLinkClick} /> <NavLinks title={'SOLDIER'} scrollValue={innerWidthProp} onLinkClick={onLinkClick} /> <NavLinks title={'SOLDIER'} scrollValue={(innerWidthProp)*2} onLinkClick={onLinkClick}/> <style jsx>{` .header-container{ position: fixed; width: 100vw; display: flex; flex-direction: row; justify-content: space-evenly; background-color: rgba(100,100,100, .2); z-index: 2; } `}</style> </div> ); }
secondchild.tsx(最内层子组件,使用props)
export const NavLinks: FC<NavLinkProps> = ({scrollValue, title, onLinkClick}): JSX.Element => { const handleClick = useCallback(() => { onLinkClick(scrollValue); }, [onLinkClick, scrollValue]) // 补充scrollValue到依赖数组,确保回调获取最新值 return ( <div> {/* 示例:渲染触发回调的按钮 */} <button onClick={handleClick}>{title}</button> </div> ) }
关键修复点
- 事件绑定优化:将
window.onresize改为addEventListener,配合useEffect清理函数移除监听,避免重复绑定和内存泄漏。 - 组件层级梳理:将state统一放在最外层父组件,通过中间层组件逐层转发props,确保state更新能完整传递到最内层子组件。
- useCallback依赖补全:原代码中
handleClick的useCallback依赖数组缺少scrollValue,导致回调始终引用旧值,修复后补充该依赖,保证回调能获取最新props。
内容的提问来源于stack exchange,提问作者bitchwhocodes
相关产品推荐
相关产品推荐

