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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:39:02