Redux-Toolkit 未更新 React 逻辑部分中的状态

问题描述 投票:0回答:1

我在 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

如何更新逻辑部分的状态?

reactjs redux redux-toolkit
1个回答
0
投票

问题在于,在实例化

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]);
© www.soinside.com 2019 - 2024. All rights reserved.