SolidJS中更新store值时createEffect触发无限循环问题
问题原因与修复方案
问题根因
- 无限循环触发:你的
createEffect每次执行都会调用setState修改state,而createEffect会监听state的变化,导致effect反复执行。当所有Todo完成后,每次effect都会给days加1,接着又触发下一次effect,无限循环直至递归溢出。 - 不必要的状态更新:你在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
相关产品推荐
相关产品推荐

