我有以下代码;
export default () => {
const [gameState, setGameState] = useState(GameStateMap.MAINMENU);
const getGameComponent = useMemo(() => {
switch (gameState) {
case "MainMenu":
return <MainMenu />
case "Game":
return <Game />
case "GameOver":
return <GameOver />
default:
throw new Error("Invalid Component");
}
})
return (
<Wrapper>
{getGameComponent}
</Wrapper>
)
}
我打算让MainMenu
,Game
和GameOver
都可以访问setGameState
。我最好的选择只是将setGameState依次传递给每个游戏,还是有更常规的选择?
答案 0 :(得分:0)
当前,您调用(<MainMenu/>
),然后分配(getGameComponent =
)
您应该分配,然后调用,然后可以向其传递道具:
export default () => {
const [gameState, setGameState] = useState(GameState.MAINMENU);
// Component should be Uppercased
const GameComponent = useMemo(() => {
switch (gameState) {
case "MainMenu":
return MainMenu;
break;
case "Game":
return Game;
break;
case "GameOver":
return GameOver;
break;
default:
throw new Error("Invalid Component");
}
});
return (
<Wrapper>
<GameComponent onGameStateChange={setGameState} />
</Wrapper>
);
};
更好地重写此组件(有意见)可能是:
const GAME_STATE = {
MainMenu: MainMenu,
Game: Game,
GameOver: GameOver,
};
export default () => {
const [gameState, setGameState] = useState(GameState.MAINMENU);
const GameComponent = GAME_STATE[gameState];
// Better show error in the UI and not a runtime exception.
return (
<Wrapper>
{GameComponent ? (
<GameComponent onGameStateChange={setGameState} />
) : (
`No such game state`
)}
</Wrapper>
);
};
答案 1 :(得分:0)
关于这一方面有两种思想流派。第一种叫做螺旋钻,这是您在原始问题中建议做的。第二个是使用React Context。我过去都用过。两者都有好处和缺点。我更喜欢使用上下文。但是,这是我的看法。
这里是一篇文章,解释了两者之间的区别。 https://medium.com/@jtonti/context-vs-prop-drilling-in-react-aa88fff7cd44
关于操作方法,请参见下文。
// in App.js or your main page
export default () => {
const [gameState, setGameState] = useState(GameStateMap.MAINMENU);
const getGameComponent = useMemo(() => {
switch (gameState) {
case "MainMenu":
return <MainMenu setGameState={setGameState} />
case "Game":
return <Game setGameState={setGameState} />
case "GameOver":
return <GameOver setGameState={setGameState} />
default:
throw new Error("Invalid Component");
}
})
return (
<Wrapper>
{getGameComponent}
</Wrapper>
)
}
// in MainMenu
...
const {setGameState} = props // or this.props if using classes
// code to use setGameState
...
用于使用上下文
// in app.js
const AppContext = React.CreateContext();
export default () => {
const [gameState, setGameState] = useState(GameStateMap.MAINMENU);
const getGameComponent = useMemo(() => {
switch (gameState) {
case "MainMenu":
return <MainMenu />
case "Game":
return <Game />
case "GameOver":
return <GameOver />
default:
throw new Error("Invalid Component");
}
})
return (
<Wrapper>
<AppContext.Provider value={{setGameState}}>
{getGameComponent}
</AppContext.Provider>
</Wrapper>
)
}
// in MainMenu
...
const {setGameState} = useContext(AppContext);
...