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

React Context传递函数更新状态数组时视图不更新及状态重置问题

问题原因

你遇到的问题由两个典型的React开发错误导致:

  1. 违反状态不可变原则
    你最初的AddOne实现直接修改原数组的引用,linesTmp和原lines是同一个内存地址,React对state做浅比较时认为状态没有变化,因此跳过了组件重渲染,这是首次点击按钮列表不更新的原因。使用setLines([...lines, text])生成新数组的写法解决了这个问题。
  2. 闭包陷阱
    你在Provider组件的空依赖useEffect中仅在组件挂载时向Context注入了一次addOne函数,这个函数捕获的是首次渲染时的lines初始值(空数组)。之后每次调用addOne时,都是基于这个初始空数组计算新状态,所以每次调用都会覆盖之前的更新内容,表现为状态被重置。

修复方案

修改AddOne函数为函数式更新,直接从React内部拿到最新的state值,不需要依赖外部的lines变量,从根源避免闭包问题。如果需要减少Context的更新频率,可以搭配useCallback稳定函数引用。

修复后的Provider组件完整代码:

import React, {useEffect, useState, useCallback} from 'react';

type ProviderProps = {
    setActions: React.Dispatch<React.SetStateAction<{
        addOne?: ((t: string) => void)
    }>>
}

const Provider = ({setActions}: ProviderProps) => {
    const [lines, setLines] = useState<string[]>([])

    // 用函数式更新+useCallback,稳定函数引用,避免闭包问题
    const AddOne = useCallback((text: string) => {
        setLines(prevLines => [...prevLines, text])
    }, [setLines])

    useEffect(() => {
        setActions({addOne: AddOne})
    }, [AddOne, setActions])

    return (<>
        <h1>Lines : </h1>
            {lines.map((line, index) => (
            <p key={index}>{line}</p>
        ))}
    </>)
}

export default Provider;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:42:00