首页 > 解决方案 > React 组件在加载时“闪烁”,因为状态被覆盖

问题描述

我使用 React 开发了一个待办事项应用程序,事情变得更加清晰,但我很难理解“生命周期”。在 VueJS 中,我知道一个ComponentDidMount()钩子,如果我猜它会帮助我解决这个问题,但在 React 中我找不到它。

我有一系列这样的待办事项:const todos = [{description: "walk dog", done: false}]

这是我的应用程序的初始状态:

const [alltodos, handleTodos] = useState([]);

在加载时,我使用这个useEffect钩子从 localStorage 获取数据。

  useEffect(() => {
    const items = localStorage.getItem("todos");
    const parsed = JSON.parse(items);
    handleTodos(parsed);
  }, []);

我用这个函数计算我的待办事项:

  const countTodos = () => {
    const donetodos = alltodos.filter((item) => {
      return !item.done;
    });

    countOpen(donetodos.length);
  };

如果依赖项发生变化,我会更新计数:

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

所以会发生什么,计数器从 0 开始,然后“闪烁”一毫秒,然后显示我从本地存储中获得的待办事项数量。

有没有办法防止这种行为?据我所知,组件首先呈现,然后触发 useEffect 挂钩。从本地存储中提取数据后如何渲染组件?

标签: javascriptreactjsreact-hooksuse-state

解决方案


用初始化allTodos状态null。只要这个状态是null,渲染一个通知或者只是返回null什么都不渲染。

您可以直接从当前alltodos状态计算打开的待办事项计数,而无需useEffect.

const [alltodos, handleTodos] = useState(null);

useEffect(() => {
  const items = localStorage.getItem("todos");
  const parsed = items ? JSON.parse(items) : [];
  handleTodos(parsed);
}, []);

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

if(alltodos === null) return 'Loading todos list';

// this is derived from state, so you don't have to create a state for it
const openTodosCount = alltodos.reduce((acc, o) => acc + !o.done, 0);

推荐阅读