React计数器组件为何两次打印console.log?求解决方案
React组件重复打印问题排查与解决
问题描述
Small组件无论是首次创建还是点击+1按钮时,console.log都会输出两次,尝试用memo处理无效。
相关代码
App.js
import { useCounter } from "../Hooks/useCounter"; import { Small } from "./Small"; export const Memorize = () => { const {counter, increment} = useCounter(10) return( <> <Small value={counter}/> <button onClick={event => increment()}> +1 </button> </> ) }
useCounter.js(计数器功能正常)
import { useState } from "react"; export const useCounter = (initialValue = 0) => { const [counter, setCounter] = useState(initialValue) const increment = (value = 1) => setCounter(counter + value) return { counter, increment, setCounter } }
Small.js
export const Small = ({value}) => { console.log('Iam console log...'); return ( <small>{value}</small> ) }
现象
每次点击+1按钮,控制台输出:
Iam console log... Iam console log...
解决方法
1. 移除React严格模式(开发环境)
这是最常见的触发原因。React 18的严格模式会在开发环境下强制触发两次组件渲染,目的是提前暴露潜在的副作用问题,生产环境不会有这个行为。
找到项目入口文件(通常是index.js),检查是否包裹了<React.StrictMode>,移除后重复打印问题会直接消失:
// index.js 修改后 import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import { Memorize } from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( // 移除<React.StrictMode>包裹 <Memorize /> );
2. 正确使用memo优化组件
若需要保留严格模式,同时避免组件在value不变时重复渲染,要正确导入并使用memo:
// Small.js 修改后 import { memo } from 'react'; export const Small = memo(({value}) => { console.log('Iam console log...'); return ( <small>{value}</small> ) })
注意:严格模式下的两次渲染是框架的检查机制,memo无法阻止这种场景下的重复打印,但能避免因value未变化导致的不必要渲染。
3. 优化useCounter的函数引用(可选)
当前useCounter中的increment函数每次都会重新创建,虽不直接导致Small重复渲染,但可以用useCallback优化,提升父组件性能:
// useCounter.js 修改后 import { useState, useCallback } from "react"; export const useCounter = (initialValue = 0) => { const [counter, setCounter] = useState(initialValue) const increment = useCallback((value = 1) => { setCounter(prev => prev + value); // 改用函数式更新,避免依赖counter }, []); // 空依赖数组,确保函数只创建一次 return { counter, increment, setCounter } }
内容的提问来源于stack exchange,提问作者Hector
相关产品推荐
相关产品推荐

