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

React无限重渲染问题排查与解决(禁用useEffect)

问题根源

你直接在组件函数体中调用了AddToast方法——每次组件渲染时都会执行这个方法,而AddToast内部调用setList修改状态,这会触发组件重新渲染,如此循环往复,就造成了无限重渲染的错误。

解决方案(不使用useEffect)

方案一:直接在初始状态中添加目标Toast

如果这个蓝色Toast是组件初始化时就需要的,直接把它放进useState的初始数组里,避免在渲染流程中动态添加:

import React, { useState } from 'react';
import styled from 'styled-components';
import { Toast, ToastProps } from './Toast';

const YourComponent = () => {
  // 初始状态直接包含三个Toast
  const [list, setList] = useState<ToastProps[]>([
    { title: '제목', message: 'Message', type: 'GREEN', id: 1 },
    { title: '오류', message: 'Message', type: 'RED', id: 2 },
    { title: '제목', message: '메세지', type: 'BLUE', id: 3 },
  ]);

  const AddToast = (
    title: string,
    message: string,
    type: 'GREEN' | 'RED' | 'YELLOW' | 'BLUE'
  ) => {
    const toastProperties = {
      id: list.length + 1,
      type,
      title,
      message,
    };
    // 用函数式更新获取最新状态,避免闭包问题
    setList(prevList => [...prevList, toastProperties]);
  };

  return (
    <_Container>
      {list.map((item) => {
        const { title, message, type, id } = item;
        // 给Toast添加唯一key,防止组件重复挂载导致动画重置
        return <Toast key={id} type={type} title={title} message={message} />;
      })}
    </_Container>
  );
};

方案二:用ref标记首次渲染,仅执行一次AddToast

如果必须动态添加(比如初始状态不能硬编码),可以用useRef记录是否已经执行过添加操作,避免每次渲染都触发:

import React, { useState, useRef } from 'react';
import styled from 'styled-components';
import { Toast, ToastProps } from './Toast';

const YourComponent = () => {
  const [list, setList] = useState<ToastProps[]>([
    { title: '제목', message: 'Message', type: 'GREEN', id: 1 },
    { title: '오류', message: 'Message', type: 'RED', id: 2 },
  ]);
  // 用ref标记是否为首次渲染
  const isFirstRender = useRef(true);

  const AddToast = (
    title: string,
    message: string,
    type: 'GREEN' | 'RED' | 'YELLOW' | 'BLUE'
  ) => {
    const toastProperties = {
      id: list.length + 1,
      type,
      title,
      message,
    };
    setList(prevList => [...prevList, toastProperties]);
  };

  // 仅在首次渲染时执行AddToast
  if (isFirstRender.current) {
    AddToast('제목', '메세지', 'BLUE');
    isFirstRender.current = false;
  }

  return (
    <_Container>
      {list.map((item) => {
        const { title, message, type, id } = item;
        return <Toast key={id} type={type} title={title} message={message} />;
      })}
    </_Container>
  );
};
关于Toast动画重置的说明

之前用useEffect时动画重置,核心原因是没有给Toast组件设置唯一且稳定的key。给每个Toast绑定它的id作为key后,React会识别组件的唯一性,只会更新内容而非卸载重建,动画就能正常运行,不会被重新初始化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:10:29