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

React点击按钮随机选数组项追加列表及状态更新问题求助

问题修复方案

错误根因

  • 状态类型与更新逻辑错误:初始化arrayList为数组类型,但现有代码直接执行setArray(randomName.name),将状态整体覆盖为单个字符串,完全丢失历史列表数据,无法实现追加效果。
  • 状态更新滞后是React状态异步更新特性导致的:React的state不会在setState调用后立刻同步修改,若在setArray调用后直接读取arrayList,拿到的永远是更新前的旧值,视觉上就会呈现“慢一拍”的效果。

修正代码

1. 修正状态更新逻辑

使用函数式更新写法,基于上一次的最新状态追加新元素,避免状态不同步:

// nameArray本地文件无需修改
export const nameArray = [
  { id: 1, name: "Folly" },
  { id: 2, name: "Leaf Blight" },
  { id: 3, name: "Caesura" }
];

// NameButton组件无需修改
function NameButton({ onClick, className, text }) {
  return (
    <button onClick={onClick} className={className}>
      {text}
    </button>
  )
};

// App组件修正
function App() {
  // 建议将setArray重命名为setArrayList,语义更清晰,避免和数组操作方法混淆
  const [arrayList, setArrayList] = useState([]);
    
  function handleClick() {
    const randomName = nameArray[Math.floor(Math.random() * nameArray.length)];
    // 函数式更新:prevList为当前最新的状态值,展开后追加新的name,返回全新数组
    setArrayList(prevList => [...prevList, randomName.name]);
  }

  return (
    <div className="App">
      <Heading />
      <NameButton className="name-button" onClick={handleClick} text="Generate Name" />
      {/* 直接传入arrayList即可,移除多余的斜体标记 */}
      <List text={arrayList} />               
    </div>
  )
};

export default App;

// 入口index.js无需修改
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

2. List组件适配

传入的text是存储所有选中名字的数组,需要在List组件内部遍历生成列表项才能正常渲染,参考实现:

function List({ text }) {
  return (
    <ul>
      {text.map((name, idx) => <li key={idx}>{name}</li>)}
    </ul>
  )
}

注意事项

开发环境下如果出现点击一次追加两项的情况,是React.StrictMode的刻意行为——开发模式下会重复执行一次状态更新函数,帮助开发者排查不纯的副作用代码,生产环境构建后该现象会自动消失,无需额外处理。

内容的提问来源于stack exchange,提问作者Pol2974

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 18:22:21