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

useEffect不执行求助:传递ThemeChange对象后未触发回调

解决useEffect依赖对象不触发的问题

你的代码核心问题是React对useEffect依赖数组采用浅引用比较:

  • 每次组件重渲染时,你都会创建新的ThemeChange对象(哪怕属性值和上一次完全一致)
  • 你遇到的useEffect不触发情况,大概率是对依赖比较逻辑的误解——理论上每次重渲染这个新对象都会触发useEffect,但如果你的需求是仅当主题实际样式变化时触发,当前写法就不符合预期。

方案1:直接依赖状态值(推荐)

既然ThemeChange的所有属性都由dark状态决定,直接把dark作为useEffect的依赖项,这样只有当主题状态真正变化时,useEffect才会执行:

import React,{useState, useMemo, useEffect} from 'react'
import './App.css';

function App() {
  const [dark, setDark] = useState(false),
  [number, setNumber] = useState(0)
  
  const SlowFunction = num => {
    for(let i=1; i<=10000; ++i) {}
    return num*2
  }
  
  const TwiceNo = useMemo(() => {
    return SlowFunction(number)
  }, [number])

  const ThemeChange = {
      backgroundColor : dark ? 'black' : 'white',
      color : dark ? 'white' : 'black' 
  }
 
  useEffect(() => {
    console.log('theme was changed!')
  }, [dark]) // 改为依赖dark状态
  

  return (
    <div className="App">
      <input type="number" onChange = {e => {setNumber(parseInt(e.target.value), console.log(e))}} />
      <button onClick={() => setDark(e => !e)}>toggle theme</button>
      <div style={ThemeChange}>{TwiceNo}</div>
    </div>
  );
}

export default App;

方案2:用useMemo缓存ThemeChange对象

如果你必须依赖ThemeChange对象本身,可以用useMemo缓存这个对象,确保只有当dark变化时,对象的引用才会更新,避免不必要的useEffect触发:

import React,{useState, useMemo, useEffect} from 'react'
import './App.css';

function App() {
  const [dark, setDark] = useState(false),
  [number, setNumber] = useState(0)
  
  const SlowFunction = num => {
    for(let i=1; i<=10000; ++i) {}
    return num*2
  }
  
  const TwiceNo = useMemo(() => {
    return SlowFunction(number)
  }, [number])

  // 用useMemo缓存对象,仅当dark变化时重新创建
  const ThemeChange = useMemo(() => ({
      backgroundColor : dark ? 'black' : 'white',
      color : dark ? 'white' : 'black' 
  }), [dark])
 
  useEffect(() => {
    console.log('theme was changed!')
  }, [ThemeChange])
  

  return (
    <div className="App">
      <input type="number" onChange = {e => {setNumber(parseInt(e.target.value), console.log(e))}} />
      <button onClick={() => setDark(e => !e)}>toggle theme</button>
      <div style={ThemeChange}>{TwiceNo}</div>
    </div>
  );
}

export default App;

补充说明

原来的写法中,每次组件重渲染(比如修改number)都会生成新的ThemeChange对象,即使属性值没变化,React也会认为依赖项发生了改变,理论上会触发useEffect。如果你发现useEffect完全没执行,建议检查控制台是否有其他输出干扰,或者确认组件是否真的发生了重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 07:45:33