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

SolidJS中更新store值时createEffect触发无限循环问题

问题原因与修复方案

问题根因

  1. 无限循环触发:你的createEffect每次执行都会调用setState修改state,而createEffect会监听state的变化,导致effect反复执行。当所有Todo完成后,每次effect都会给days加1,接着又触发下一次effect,无限循环直至递归溢出。
  2. 不必要的状态更新:你在effect里每次都把todos()赋值给state.todos,哪怕Todo列表没有变化,也会强制更新state,进一步加剧循环问题。

修复方案

核心思路是只在Todo状态从“未全完成”变为“全完成”时,才增加打卡天数,同时避免不必要的state更新。

步骤1:扩展Store状态,增加当日完成标记

给store加一个isTodayCompleted字段,用来标记当天是否已经完成打卡,防止重复累加天数:

type Todo = {
  text: string;
  complete: boolean;
};

type AppState = {
  days: number;
  todos: Todo[];
  isTodayCompleted: boolean; // 标记当日是否已完成打卡
};

const [state, setState] = createStore<AppState>({
  days: 0,
  todos: todos(), // 假设todos是你的初始Todo列表或信号值
  isTodayCompleted: false,
});

步骤2:修改Effect逻辑,精准触发天数更新

只在Todo全完成且未标记当日完成时,才更新天数和标记;如果Todo从全完成变回未完成,重置标记:

createEffect(() => {
  const allCompleted = state.todos.every(todo => todo.complete);
  
  // 全完成且未打卡:更新天数+标记
  if (allCompleted && !state.isTodayCompleted) {
    setState({
      days: state.days + 1,
      isTodayCompleted: true,
    });
  }
  // 未全完成但已标记:重置标记
  else if (!allCompleted && state.isTodayCompleted) {
    setState({ isTodayCompleted: false });
  }
});

步骤3:正确更新Todo状态

后续修改Todo完成状态时,必须通过setState更新store里的todos,这样effect才能正确监听变化:

// 示例:切换指定Todo的完成状态
const toggleTodo = (index: number) => {
  setState('todos', index, prev => ({
    ...prev,
    complete: !prev.complete,
  }));
};

关于createMemo的补充说明

createMemo适合计算衍生值(比如当前是否全完成),但days是需要持久化的状态,不能用memo代替store。如果需要计算全完成状态,可以用memo辅助:

const isAllCompleted = createMemo(() => state.todos.every(t => t.complete));

内容的提问来源于stack exchange,提问作者dudu-av

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:00:16