React组件重渲染致背景图变更,useMemo无效该如何解决?
问题描述
我有一个React组件,会在页面每次访问时生成随机背景图,但不希望它在组件重渲染时更新。目前用户在输入框中输入文本时,背景图会随每次重渲染更换。我尝试使用useMemo Hook但未成功,请问我哪里操作有误?
export function RegisterLayout({ children, position = 'justify-center' }) { return ( ... <img src={getBackgroundImage()} alt='' className='w-100 absolute inset-0 m-auto box-border block h-0 max-h-full min-h-full w-0 min-w-full max-w-full border-none object-cover p-0' /> ... ) } const getBackgroundImage = () => { const backgroundImages = Array(backgroundImage1, backgroundImage2, backgroundImage3, backgroundImage4) const randomInt = Math.floor(Math.random() * backgroundImages.length) return backgroundImages[randomInt] } RegisterLayout.propTypes = { children: PropTypes.array, position: PropTypes.string } export default RegisterLayout
问题原因与解决方案
问题核心是你每次组件重渲染时都会调用getBackgroundImage(),每次调用都会生成新的随机数,导致背景图跟着变化。需要让随机背景图仅在组件首次挂载时生成一次,后续重渲染不再更新。
方案1:使用useState初始化函数
利用useState的初始化函数特性,它只会在组件首次挂载时执行一次:
import { useState } from 'react'; import PropTypes from 'prop-types'; export function RegisterLayout({ children, position = 'justify-center' }) { // 仅首次渲染时执行getBackgroundImage const [backgroundImage] = useState(() => getBackgroundImage()); return ( ... <img src={backgroundImage} alt='' className='w-100 absolute inset-0 m-auto box-border block h-0 max-h-full min-h-full w-0 min-w-full max-w-full border-none object-cover p-0' /> ... ) } const getBackgroundImage = () => { // 修正数组创建方式,Array()构造函数写法错误 const backgroundImages = [backgroundImage1, backgroundImage2, backgroundImage3, backgroundImage4]; const randomInt = Math.floor(Math.random() * backgroundImages.length); return backgroundImages[randomInt]; } RegisterLayout.propTypes = { children: PropTypes.array, position: PropTypes.string } export default RegisterLayout
方案2:正确使用useMemo
如果你之前尝试useMemo失败,大概率是没设置空依赖数组。正确写法如下,空数组意味着仅在首次渲染时计算值:
import { useMemo } from 'react'; // 组件内部 const backgroundImage = useMemo(() => getBackgroundImage(), []);
这个写法和useState初始化函数的效果完全一致。
额外修正点
你代码里用Array(backgroundImage1...)创建数组的写法是错误的,应该用数组字面量[],否则无法正确生成包含指定元素的数组。
内容的提问来源于stack exchange,提问作者Jon Erickson
相关产品推荐
相关产品推荐

