我想使用键盘控制我的应用程序 UI,但我不知道如何实现。 (视频播放器应用程序)我有 redux 商店,我将状态设置为控件。然后它通过 props 传递状态。我的方向正确吗?
我有组件 PlayerUI,它将状态作为 props 传递给 PlayerUIBottomBar
const PlayerUI = ({ channels, actualChannel, hlsQualityLevels }: IProps) => {
...
const handleKeyUp = async (e: KeyboardEvent) => {
if (e.key === "ArrowUp") {
dispatch(playerUIActions.setActualEpgIndex(0))
dispatch(playerUIActions.decrementChannelToChangeIndex());
}
if (e.key === "ArrowDown") {
dispatch(playerUIActions.setActualEpgIndex(0))
dispatch(playerUIActions.incrementChannelToChangeIndex());
}
if (e.key === "ArrowLeft") {
dispatch(playerUIActions.decrementActualEpgIndex())
}
if (e.key === "ArrowRight") {
dispatch(playerUIActions.incrementActualEpgIndex())
}
dispatch(playerUIActions.setIsMenuVisible(true));
}
useEffect(() => {
dispatch(getChannelsAsync());
window.addEventListener("mousemove", setIsMenuVisible);
window.addEventListener("keyup", handleKeyUp);
return () => { window.removeEventListener("mousemove", setIsMenuVisible); window.removeEventListener("keyup", handleKeyUp); }
}, []);
return (
<div className={`${playerUIState.isMenuUIVisible ? "opacity-100" : "opacity-0"} transition-opacity duration-500`}>
<PlayerUITopBar hlsQualityLevels={hlsQualityLevels} />
<PlayerUIBottomBar channels={channels} isScrollToEpgSmooth={isScrollToEpgSmooth} selectedChannelIndex={playerUIState.channelToChangeIndex} isMenuVisible={playerUIState.isMenuUIVisible} />
</div>
)
}
组件PlayerUIBottomBar。在这个组件中,我做的第一件事是将列表滚动到选定的频道
export const PlayerUIBottomBar = ({ channels, isScrollToEpgSmooth = false, selectedChannelIndex, isMenuVisible }: IProps) => {
const scrollChannel = (index: number, smooth: boolean = true) => {
const channelToScrollElem = document.getElementById(index.toString());
if (channelToScrollElem) {
channelToScrollElem.scrollIntoView({
behavior: smooth ? "smooth" : "instant"
});
}
};
if (isMenuVisible)
{
scrollChannel(selectedChannelIndex, true);}
else
setTimeout(() => {
scrollChannel(selectedChannelIndex, false);
}, 500);
return (
{channels
.filter((x) => x.enabled)
.map((channel, index) => (
<PlayerChannel
key={channel.ch_id}
channel={channel}
index={index}
handleClickChangeVideo={handleClickChangeVideo}
epgIndex={playerUIState.actualEpgIndex}
isSmoothScrollToEpg={isScrollToEpgSmooth}
/>
}
)
}
通过 props 传递状态是否是正确的方法?我应该以不同的方式处理这个问题吗?例如。 useeffect 和依赖表对状态变化做出反应,然后滚动到选定的通道?
在使用 Redux 进行状态管理的 React 应用程序中,如果状态已经存储在 Redux 存储中,则通常不需要通过 props 将状态传递给子组件。 Redux 提供了一个集中存储来管理应用程序的状态,任何组件都可以直接访问该状态,而无需通过组件层次结构向下传递。
这是在 React 中使用 Redux 的一般方法:
使用化简器和操作定义 Redux 存储来管理应用程序的状态。
在应用程序的顶层使用 React-Redux 的组件,使 Redux 存储可供所有组件使用。
使用 React-Redux 提供的连接函数或钩子(如
useSelector
和 useDispatch
)将你的组件连接到 Redux 存储。
直接在组件内访问状态并调度操作。
要为您的应用程序 UI(包括视频播放器)实现键盘控制,您可以按照以下常规步骤操作:
定义 Redux 操作: 创建 Redux 操作以根据键盘输入更新 UI 控件的状态。例如,您可能有诸如togglePlay、seekForward、seekBackward、toggleFullScreen 等操作。
实现 Redux 减速器: 编写减速器来处理这些操作并在 Redux 存储中相应地更新 UI 控件状态。
将组件连接到 Redux: 使用 React-Redux 的 connect 函数或 useSelector 和 useDispatch 等挂钩将您的 UI 组件(包括视频播放器组件)连接到 Redux 存储。
处理键盘事件:在组件层次结构中的适当级别(通常是顶级组件或特定容器组件)添加键盘事件(例如 keydown 或 keyup)的事件侦听器。
调度 Redux 操作:当相关键盘事件发生时,调度相应的 Redux 操作来更新 Redux 存储中的 UI 控件状态。
根据状态更改更新 UI: 确保您的 UI 组件订阅了 Redux 存储中的相关状态切片,并根据 UI 控件状态的更改更新其外观或行为。
通过遵循这种方法,您可以避免通过多层组件向下传递状态的需要,从而使您的代码更干净且更易于维护。此外,它还有助于使组件更加解耦,因为它们不需要了解父级的状态结构。