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
相关产品推荐
相关产品推荐

