我在 redux-toolkit 中更新状态时遇到问题。在部分 html 状态已正确更新,但在逻辑部分状态未更新。我做错了什么?
export default function TestPage() {
const playerState = useAppSelector(state => state.player);
const dispatch = useAppDispatch();
const setMenuVisible = () => dispatch(playerActions.setIsMenuVisible(true));
const handleKeyUp = (e: KeyboardEvent) => {
setMenuVisible();
// STATE IS NOT UPDATED
if (playerState.isMenuUIVisible) {
if (e.key === 'Escape') {
dispatch(playerActions.setIsFullscreen(false));
}
}
}
useEffect(() => {
document.addEventListener("keyup", handleKeyUp);
return () => {
document.removeEventListener("keyup", handleKeyUp);
}
}, []);
return (
// STATE IS UPDATE CORRECTLY
<div className={`${playerState.isMenuUIVisible ? 'opacity-100' : 'opacity-0'} transition duration-500 absolute bottom-0 h-60 w-full bg-gradient-to-b from-transparent via-neutral-900/85 to-neutral-900 flex flex-col justify-end z-0 space-y-4 pb-4`}>
<div
className={"mt-6 h-[1px] bg-gradient-to-r from-transparent via-[#008DD2] to-transparent w-full "}/>
<div className={"relative flex justify-between space-x-4 pr-4"}>
<div id={'scrollChannel'}
className={"grow overflow-y-auto h-28 space-y-8 snap-y snap-mandatory scrollbar-hide focus:outline-none"}>
</div>
</div>
<div
className={"mb-6 h-[1px] bg-gradient-to-r from-transparent via-[#008DD2] to-transparent w-full"}/>
</div>
)
}
玩家切片 在这个片段中是playerSlice
export const playerSlice = createSlice({
name: "player",
initialState: initialPlayerState,
reducers: {
setIsMenuVisible: (state: IPlayerState, action: PayloadAction<boolean>) => {
state.isMenuUIVisible= action.payload;
},
setIsFullscreen: (state: IPlayerState, action: PayloadAction<boolean>) => {
state.isFullscreen = action.payload;
},
togglePlaying: (state: IPlayerState) => {
state.playing = !state.playing;
},
togglePlaying: (state: IPlayerState) => {
state.playing = !state.playing;
},
toggleMuted: (state: IPlayerState) => {
state.muted = !state.muted;
},
},
})
export const playerActions = playerSlice.actions
export default playerSlice.reducer
如何更新逻辑部分的状态?
问题在于,在实例化
playerState
事件侦听器的初始渲染周期中,handleKeyUp
处理程序中 Redux 存储中选定的 "keyup"
值已过时关闭。
您可以将
playerState
作为依赖项包含在内,这样当其值更改时,handleKeyUp
的新副本可以重新包含要在回调中使用的当前值。
const playerState = useAppSelector(state => state.player);
const dispatch = useAppDispatch();
useEffect(() => {
const setMenuVisible = () => dispatch(
playerActions.setIsMenuVisible(true)
);
const handleKeyUp = (e: KeyboardEvent) => {
setMenuVisible();
if (playerState.isMenuUIVisible) {
if (e.key === 'Escape') {
dispatch(playerActions.setIsFullscreen(false));
}
}
}
document.addEventListener("keyup", handleKeyUp);
return () => {
document.removeEventListener("keyup", handleKeyUp);
};
}, [dispatch, playerState]);
或者您可以导入存储对象并访问处理程序中的当前值。这将删除
playerState
作为外部依赖项,您可以保留空依赖项数组(或仍然包含 dispatch
,因为它在技术上是外部依赖项,它是一个稳定的引用,可以包含)。
import { store, AppState } from '../path/to/store';
...
const playerState = useAppSelector(state => state.player);
const dispatch = useAppDispatch();
useEffect(() => {
const setMenuVisible = () => dispatch(
playerActions.setIsMenuVisible(true)
);
const handleKeyUp = (e: KeyboardEvent) => {
const playerState = (store.getState() as AppState).player;
setMenuVisible();
if (playerState.isMenuUIVisible) {
if (e.key === 'Escape') {
dispatch(playerActions.setIsFullscreen(false));
}
}
}
document.addEventListener("keyup", handleKeyUp);
return () => {
document.removeEventListener("keyup", handleKeyUp);
};
}, [dispatch]);