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

React TypeScript中如何用useCookies加载浏览器Cookie并同步状态

问题场景

  • 搭建了基础React TypeScript项目,用来测试Cookie的存、取及值同步逻辑
  • App.tsx:点击按钮递增myNumber状态,把这个值传给Save组件
  • Save.tsx:通过useCookies将myNumber转成字符串,保存为名为cookie-number的Cookie
  • Load.tsx:能读取该Cookie的值,但没法同步到App.tsx的myNumber状态,导致无法基于已存的Cookie值继续递增

试过的错误方法及问题

  • 在App.tsx的useEffect里直接调用Load()组件函数:触发无效钩子调用错误(React钩子只能在组件顶层调用,不能在effect里调用组件)
  • 把Load()的结果传入Save组件:提示元素无法设为字符串(Load是React组件,返回的是JSX元素,不是原始数值)
  • 用Load()结果初始化myNumber:无Cookie时出现NaN无法递增(无Cookie时读取到undefined,转数字变成NaN)

正确实现方案

核心是把Cookie的读写逻辑从组件里抽成自定义钩子,组件只负责UI展示,逻辑统一管理。

1. 写一个可复用的Cookie自定义钩子(useCookie.ts)

import { useCookies } from 'react-cookie';

export const useCookieNumber = () => {
  const [cookies, setCookie] = useCookies(['cookie-number']);

  // 读取Cookie,处理无值的情况,默认返回0
  const getCurrentNumber = () => {
    const cookieVal = cookies['cookie-number'];
    return cookieVal ? parseInt(cookieVal, 10) : 0;
  };

  // 保存Cookie,确保存的是字符串格式
  const saveCookieNumber = (num: number) => {
    setCookie('cookie-number', num.toString(), { path: '/' });
  };

  return {
    currentNumber: getCurrentNumber(),
    saveCookieNumber
  };
};

2. 重构App.tsx,直接用自定义钩子

import { useState, useEffect } from 'react';
import { useCookieNumber } from './useCookie';

function App() {
  const { currentNumber, saveCookieNumber } = useCookieNumber();
  // 用Cookie里的初始值初始化myNumber,无Cookie时就是0
  const [myNumber, setMyNumber] = useState<number>(currentNumber);

  // 当myNumber变化时自动同步到Cookie
  useEffect(() => {
    saveCookieNumber(myNumber);
  }, [myNumber, saveCookieNumber]);

  const handleIncrement = () => {
    setMyNumber(prev => prev + 1);
  };

  return (
    <div>
      <p>当前数值:{myNumber}</p>
      <button onClick={handleIncrement}>点击递增</button>
    </div>
  );
}

export default App;

3. 拆分UI组件(可选)

如果想把UI和逻辑分开,可以把展示部分拆成独立组件,比如:

// Display.tsx
type DisplayProps = {
  number: number;
  onIncrement: () => void;
};

export function Display({ number, onIncrement }: DisplayProps) {
  return (
    <div>
      <p>当前数值:{number}</p>
      <button onClick={onIncrement}>点击递增</button>
    </div>
  );
}

然后在App.tsx里替换返回内容:

// ...其他代码
return <Display number={myNumber} onIncrement={handleIncrement} />;

为什么之前的方法不行?

  1. 无效钩子调用:React组件内部会调用钩子,而钩子必须在组件的顶层调用,不能在useEffect、循环或条件里调用组件,这违反了React的钩子规则。
  2. 元素无法设为字符串:Load是React组件,调用它得到的是JSX元素对象,不是Cookie的数值,自然不能当字符串传给Save组件。
  3. NaN问题:无Cookie时读取到的是undefined,直接转数字会变成NaN,必须加默认值兜底,确保初始值是有效的数字0。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:52:35