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

为什么在useEffect中调用setState后组件没有触发重新渲染?

useEffect调用setState后组件未重新渲染问题排查与解决

问题描述

请问为什么我在useEffect内部调用setState后组件没有重新渲染?我在谷歌上搜索到的资料显示,在useEffect中调用setState会触发组件重新渲染。

我的代码如下:

export default function CarouselMusicGenres() {
    const [musicGenres, setMusicGenres] = useState(null)

    const setAllMusicGenres = () => {
        MusicGenresAPI.getAll()
            .then((response) => {
                if (response.status === 200) {
                    setMusicGenres(response.data.musicGenres)
                }
            })
            .catch((error) => {
                console.log(error)
            })
    }

    const displayAllMusicGenres = () => {
        if (musicGenres && musicGenres.length > 0) {
            musicGenres.forEach((musicGenre) => {
                return (
                    <SwiperSlide>
                        <Col
                            className="genre"
                            style={{
                                backgroundImage: `url(/assets/images/music-genres/${musicGenre.image_background_url})`,
                            }}
                        >
                            <span>{musicGenre.genre}</span>
                            <div className="transparent-background"></div>
                        </Col>
                    </SwiperSlide>
                )
            })
        }
    }

    useEffect(() => {
        setAllMusicGenres()
    }, [])

    return (
        <Row className="carousel-genres">
            <Swiper spaceBetween={10} slidesPerView={6}>
                {displayAllMusicGenres()}
            </Swiper>
        </Row>
    )
}

我还尝试过用以下代码替代useEffect逻辑,问题依然没有解决:

if (!musicGenres) {
    setAllMusicGenres()
}

问题根因

你的组件实际上已经触发了重渲染,问题出在displayAllMusicGenres方法的实现上:
forEach方法仅遍历数组,本身没有返回值,你在forEach回调中返回的JSX元素不会被收集,所以整个displayAllMusicGenres函数最终返回的是undefined,页面自然不会渲染出内容,看起来就像没有触发重渲染一样。

解决方案

将forEach替换为map,同时在musicGenres.map前添加return语句,修改后的displayAllMusicGenres代码如下:

const displayAllMusicGenres = () => {
    if (musicGenres && musicGenres.length > 0) {
        // 把forEach换成map,外层加return
        return musicGenres.map((musicGenre) => (
            <SwiperSlide key={musicGenre.id /* 建议添加唯一key,避免React告警 */}>
                <Col
                    className="genre"
                    style={{
                        backgroundImage: `url(/assets/images/music-genres/${musicGenre.image_background_url})`,
                    }}
                >
                    <span>{musicGenre.genre}</span>
                    <div className="transparent-background"></div>
                </Col>
            </SwiperSlide>
        ))
    }
}

额外优化建议:渲染列表元素时最好给每一项添加唯一的key属性,可以避免React的列表渲染告警,优化重渲染性能。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 18:36:08