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

React Context Provider更新后组件函数内值未同步问题

React Context状态更新后组件函数内值未同步的解决方案

问题分析

  1. Provider内console.log未更新:setCompany是异步操作,调用后立即访问company状态拿到的仍是更新前的旧值,这是React状态更新的异步特性导致的。
  2. 组件handlePickerChange获取旧ID:回调函数因闭包捕获了旧的company引用,或回调未随company更新而重新创建,导致触发时使用旧数据。

具体修复步骤

1. 修复Provider的状态日志问题

将状态更新后的日志逻辑移至监听company变化的useEffect中,确保获取最新状态:

export const CompanyProvider: React.FC<CompanyProviderProps> = ({
  children,
}) => {
  const { companyId } = useParams();
  const [company, setCompany] = useState<EntrepriseReceiveInterface | null>(
    null
  );
  const [loading, setLoading] = useState<boolean>(true);

  if (!companyId) {
    return <h1>Erreur</h1>;
  }

  const getCompanyUnique = EntrepriseGetByIdUseCase(companyId);

  useEffect(() => {
    if (getCompanyUnique.status === "success") {
      const body = getCompanyUnique.data.body;
      console.log("body", body);
      setCompany(body);
      setLoading(false);
    }
  }, [getCompanyUnique.status, companyId]);

  // 监听company变化,打印最新值
  useEffect(() => {
    console.log("company(最新)", company);
  }, [company]);

  return (
    <CompanyContext.Provider value={{ company, setCompany }}>
      {loading ? <div>Chargement...</div> : children}
    </CompanyContext.Provider>
  );
};

2. 修复组件回调的旧值问题

使用useCallback包裹回调函数,确保其随company更新而重新创建,捕获最新状态:

const { company, setCompany } = useCompany();
if (!company) {
  return <h1>Erreur</h1>;
}
const { mutate: setColorMutation } = useEditCompanyColor();

console.log("company", company._id);

// 用useCallback包裹,依赖项包含所有外部引用
const handlePickerChange = useCallback((color: any) => {
  console.log(company._id);
  setColorMutation(
    { entrepriseId: company._id, color: color.hex },
    {
      onSuccess: () => {
        setCompany((prevCompany) =>
          prevCompany ? { ...prevCompany, colorPrimary: color.hex } : null
        );
        toast.success("Vous avez bien changé la couleur primaire", {
          style: { borderColor: "var(--successHexa)" },
        });
      },
      onError: () => {
        toast.error("Une erreur est survenue, veuillez réessayer", {
          style: { borderColor: "var(--errorHexa)" },
        });
      },
    }
  );
}, [company, setColorMutation, setCompany]);

return (
  <Card className="flex justify-between items-center h-full">
    <CardHeader>
      <CardTitle>Couleur - Entreprise</CardTitle>
      <CardDescription>Choisissez votre couleur d'entreprise</CardDescription>
    </CardHeader>
    <CardContent className="flex flex-col xl:flex-row p-0 pt-2 pb-2 pr-6 xl:pt-0 xl:pb-0 items-center space-x-2">
      <div
        className="text-2xl font-bold rounded-full w-16 h-16"
        style={{ backgroundColor: company.colorPrimary }}
      ></div>
      {company._id}
      <Compact
        color={company.colorPrimary}
        onChange={handlePickerChange}
      />
    </CardContent>
  </Card>
);

关键原理总结

  • React状态更新是异步的,不能在调用setState后立即获取新状态,需通过useEffect监听状态变化。
  • 依赖外部状态的组件回调,必须用useCallback包裹并设置完整依赖项,避免闭包捕获旧值导致逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:56:03