Redux状态更新时useEffect钩子未触发的问题求助
Redux状态更新时useEffect钩子未触发的问题求助
我有一个简单的Tile组件,希望在hover时改变颜色(以及关联组件的样式)。目前我在组件hover时更新Redux状态,DevTools显示状态确实更新了,但监听该状态的useEffect钩子从未触发,组件也没有正确切换样式。以下是我的代码,麻烦帮忙排查问题:
Tile组件代码
import React, { useEffect } from 'react'; import { useDispatch, useSelector, } from 'react-redux'; import { setSelectedTile } from './app/slices/tileSlice'; import Player from './Player'; const baseTileStyles = { backgroundColor: "lightgray", transition: "ease 500ms background-color", display: "flex", alignItems: "center", justifyContent: "center", height: "100%", width: "100%" }; const selectedStyles = { ...baseTileStyles, backgroundColor: "gray" }; const getTileStyle = isSelected => { return isSelected ? selectedStyles : baseTileStyles; }; export const Tile = (props) => { const dispatch = useDispatch() let tilestate = useSelector(state => state.selectedTile) useEffect(() => { console.log('selectedTile updated %d', tilestate) }, [tilestate]) return ( <div onMouseEnter={() => dispatch(setSelectedTile(props.id))} style={getTileStyle(tilestate === props.id)}> <Player streamUrl={props.streamUrl} isSelected={props.isSelected} /> </div> ) } export default Tile;
Tile Slice代码
import { createSlice } from '@reduxjs/toolkit' export const tileSlice = createSlice({ name: 'tile', initialState: { selectedTile: 1, clickedTile: null }, reducers: { setClickedTile: (state, action) => { if (state.clickedTile === action.payload) { return { ...state, clickedTile: null } } else { return { ...state, clickedTile: action.payload, selectedTile: action.payload } } }, setSelectedTile: (state, action) => { if (!state.clickedTile) { return { ...state, selectedTile: action.payload } } } } }) export const { setClickedTile, setSelectedTile } = tileSlice.actions export default tileSlice.reducer
Store配置代码
import { configureStore } from '@reduxjs/toolkit' import tileReducer from './slices/tileSlice' import urlReducer from './slices/urlSlice' import showHelpReducer from './slices/showHelpSlice' export default configureStore({ reducer: { window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), tile: tileReducer, url: urlReducer, showHelp: showHelpReducer, } })
问题排查与修复
我帮你找到了两个核心问题,修复后就能解决useEffect不触发和样式不更新的问题:
1. Store配置的致命错误
你把Redux DevTools的扩展函数错误地放到了reducer对象里!configureStore的reducer字段只能存放各个slice的reducer映射,DevTools是单独的配置项(而且@reduxjs/toolkit的configureStore默认已经启用了DevTools,不需要手动添加)。
修复后的Store代码:
import { configureStore } from '@reduxjs/toolkit' import tileReducer from './slices/tileSlice' import urlReducer from './slices/urlSlice' import showHelpReducer from './slices/showHelpSlice' export default configureStore({ reducer: { // 移除错误放入的DevTools函数,只保留reducer映射 tile: tileReducer, url: urlReducer, showHelp: showHelpReducer, }, // 如果你需要自定义DevTools配置,可以加这个选项,默认启用状态下可以省略 // devTools: process.env.NODE_ENV !== 'production' })
2. useSelector的状态路径错误
因为你把tileReducer挂载到了store的tile字段下,所以Redux的state结构是{ tile: { selectedTile: ..., clickedTile: ... }, ... }。但你当前的useSelector直接取state.selectedTile,这会返回undefined(根state下没有这个字段),自然无法响应状态更新。
修复Tile组件里的useSelector:
// 错误写法 // let tilestate = useSelector(state => state.selectedTile) // 正确写法:从state.tile子节点下获取selectedTile let tilestate = useSelector(state => state.tile.selectedTile)
修复后的效果
当你完成以上两处修复后:
tilestate会正确同步Redux中tile.selectedTile的状态变化- 状态更新时
useEffect会被触发,控制台会打印更新日志 - 组件会根据
tilestate === props.id的判断正确切换样式
备注:内容来源于stack exchange,提问作者Ed McKenna
相关产品推荐
相关产品推荐

