You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
    )
}

关键修复点

  1. 事件绑定优化:将window.onresize改为addEventListener,配合useEffect清理函数移除监听,避免重复绑定和内存泄漏。
  2. 组件层级梳理:将state统一放在最外层父组件,通过中间层组件逐层转发props,确保state更新能完整传递到最内层子组件。
  3. useCallback依赖补全:原代码中handleClick的useCallback依赖数组缺少scrollValue,导致回调始终引用旧值,修复后补充该依赖,保证回调能获取最新props。

内容的提问来源于stack exchange,提问作者bitchwhocodes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 15:18:14