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

使用useRef、localStorage和useState实现页面刷新后保留状态可行吗?

页面刷新保留状态的方案解析

问题背景

我想实现页面刷新后保留状态的功能,目前考虑结合localStorage与useRef的方案,但不确定这个方案技术上是否正确,想请教:

  • useRef是否适用于这类场景?
  • 有没有更便捷的替代方案?

项目是小型电影应用,无需数据库,localStorage的5MB容量完全足够。

现有代码实现

State(从API获取)

const [popularMovies, setPopularMovies] = useState(false);

获取状态数据

function getPopularMoviesData() {
  const url =
    "https://api.themoviedb.org/3/movie/popular?api_key=60186105dc57d2473a4b079bdee2fa31&language=en-US&page=1";

  fetch(url)
    .then((response) => response.json())
    .then((data) => {
      setPopularMovies(data);
    })
    .catch((err) => console.error(err));
}

useEffect(() => {
  getPopularMoviesData();
}, []);

useRef相关代码

const prevPopularMovies = useRef();

尝试在重渲染后保留旧数据

useEffect(() => {
  prevPopularMovies.current = popularMovies;
  setPopularMovies(prevPopularMovies.current);
});

localStorage保留刷新后数据

useEffect(() => {
  const popularMoviesData = localStorage.getItem("popularMovies");

  if (popularMoviesData !== null) {
    setPopularMovies(JSON.parse(popularMoviesData));
  }
}, []);

useEffect(() => {
  localStorage.setItem("popularMovies", JSON.stringify(popularMovies));
}, [popularMovies]);

方案解答

1. useRef是否适用于这个场景?

完全不适用。useRef的核心是保存跨重渲染周期的内存变量,它的数据不会触发组件重渲染,而且页面刷新后,组件实例被销毁,useRef里的数据会直接丢失——因为它只存在内存中,和localStorage的持久化存储完全不是一个维度的功能。

另外你当前的useRef相关代码还有严重问题:不带依赖项的useEffect会在每次重渲染都执行,里面调用setPopularMovies又会触发重渲染,直接导致无限循环,这是必须要避免的。

2. 更便捷的替代方案

既然已经确定用localStorage,完全不需要useRef,直接优化现有逻辑即可,甚至可以封装成复用性更强的自定义Hook:

优化后的基础实现

// 初始化时优先从localStorage读取缓存
const [popularMovies, setPopularMovies] = useState(() => {
  const saved = localStorage.getItem("popularMovies");
  return saved ? JSON.parse(saved) : null; // 用null替代false,更符合数据状态
});

function getPopularMoviesData() {
  const url =
    "https://api.themoviedb.org/3/movie/popular?api_key=60186105dc57d2473a4b079bdee2fa31&language=en-US&page=1";

  fetch(url)
    .then((response) => response.json())
    .then((data) => {
      setPopularMovies(data);
    })
    .catch((err) => console.error(err));
}

// 只有无本地缓存时才请求API,减少不必要的网络请求
useEffect(() => {
  if (!popularMovies) {
    getPopularMoviesData();
  }
}, [popularMovies]);

// 状态更新时同步到localStorage
useEffect(() => {
  if (popularMovies) {
    localStorage.setItem("popularMovies", JSON.stringify(popularMovies));
  }
}, [popularMovies]);

进阶:封装自定义Hook(复用逻辑)

如果后续还有其他状态需要本地缓存,可以封装一个通用Hook:

function useLocalStorageState(key, initialValue) {
  const [state, setState] = useState(() => {
    const saved = localStorage.getItem(key);
    return saved ? JSON.parse(saved) : initialValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(state));
  }, [key, state]);

  return [state, setState];
}

// 使用方式
const [popularMovies, setPopularMovies] = useLocalStorageState("popularMovies", null);

这样所有需要持久化的状态都能直接复用这个逻辑,代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:15:18