React使用Generator实现双向循环切换组件的bug排查咨询
问题原因
1. 初始值异常&点击两次才切换的原因
- Generator的
next()方法传参规则:第一次调用next()传入的参数会被直接忽略,只有后续调用的参数才会作为上一条yield语句的返回值。 - React 18 开发环境默认开启严格模式,组件初始化时会执行两次
useState的初始化函数,等于连续调用了两次getNext():第一次返回one,第二次执行时把"forward"赋值给direction,下标计算为1,返回two,所以最终初始值是two。 - 当你改成直接用
array[0]初始化时,Generator实例没有被调用过next(),第一次点击right调用getNext()是第一次执行next(),返回steps[0]也就是one,和当前状态相同所以没有变化,第二次点击才会返回two,就出现了需要点击两次的问题。
2. left按钮失效的原因
JS 中取模运算的结果符号和被除数一致,当index为0时,减1得到-1,-1 % 3 = -1,用负数下标访问数组得到undefined,所以left点击后展示异常,看起来像失效。
解决方案
调整Generator逻辑、下标计算方式,同时匹配初始化逻辑即可:
import { useState } from "react"; // 调整Generator逻辑,兼容首次调用,同时修复负数下标问题 function* stepGen(steps) { let index = 0; // 首次调用next直接返回第一项,不需要处理方向参数 yield steps[index]; while (true) { const direction = yield steps[index]; const offset = direction === "forward" ? 1 : -1; // 修复负数取模问题,确保下标始终在合法范围内 index = (index + offset + steps.length) % steps.length; } } const array = ["one", "two", "three"]; const gen = stepGen(array); // 提前调用一次next拿到初始值,避免严格模式下初始化重复调用问题 const initialValue = gen.next().value; const getNext = () => gen.next("forward").value; const getPrev = () => gen.next("backward").value; export default function App() { const [current, setCurrent] = useState(initialValue); const onRight = () => setCurrent(getNext()); const onLeft = () => setCurrent(getPrev()); return ( <div className="App"> <h1>{current}</h1> <button onClick={onLeft}>left</button> <button onClick={onRight}>right</button> </div> ); }
内容的提问来源于stack exchange,提问作者Joji
相关产品推荐
相关产品推荐

