redux 基于全局状态显示组件的提示

b0zn9rqh  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(143)

我正在构建的游戏界面具有以下用户流:
用户登陆其中一个游戏URL,例如www.name.com/game1,首先得到介绍屏幕,然后是游戏屏幕,最后是失败或成功屏幕。
我正在尝试找出最佳的方法来实现这个目标。贝娄的代码运行得很好,但我在寻找更优雅和可扩展的解决方案。你有什么想法吗?

import { useParams } from "react-router-dom";
import { useSelector } from "react-redux";

// Import views and components
import Step1 from "../Intro/Step1";
import StatusBar from "../../components/StatusBar/StatusBar";
import Game1 from "./Games/Game1/Game1";
import Game2 from "./Games/Game2/Game2";
import Intro from "./Intro/Intro";
import Password from "./Password/Password";
import Success from "./Success/Success";
import Fail from "./Fail/Fail";
import FailBeginOnStart from "./Fail/FailBeginOnStart";

// Data

function Game() {
  const data = {
    game1: {
      desc: "some description for game 1",
    },
    game2: {
      desc: "some description for game 2",
    },
  };

  // Get global states from redux toolkit
  const showIntro = useSelector((state) => state.game.showIntro);
  const showSuccess = useSelector((state) => state.game.showSuccess);
  const showFail = useSelector((state) => state.game.showFail);
  const showPassword = useSelector((state) => state.game.showPassword);
  const completedGame = useSelector((state) => state.game.completedGame);
  const selectedLanguage = useSelector((state) => state.game.selectedLanguage);

  // Get current param from URL (example /game1)
  const { game } = useParams();

  // Strip slash to get matching game ID (example game1)
  const gameId = game.replace(/-/g, "");

  const GameScreen = () => {

    // show intro screen
    if (showIntro === true) {
      return (
        <>
          <StatusBar />
          <Intro path={game} id={gameId} data={data[gameId]} />
        </>
      );
    }

    // show success screen
    if (showSuccess === true) {
      return (
        <>
          <StatusBar />
          <Success data={data[gameId]} />
        </>
      );
    }

    // show fail screen
    if (showFail === true) {
      return (
        <>
          <StatusBar />
          <Fail data={data[gameId]} />
        </>
      );
    }

    // Show actual game
    switch (true) {
      case game === "game1":
        return <Game1 data={data[gameId]} />;
      case game === "game2":
        return <Game2 data={data[gameId]} />;
      default:
        return <Step1 />;
    }
  };

  return <GameScreen />;
}

export default Game;
zkure5ic

zkure5ic1#

我建议使用React Router,并将其改为基于类的组件。您可以将BaseGame类作为具体游戏的模板。(如果您使用的是typescript,则可以将其设置为抽象类。)
这些示例没有提供有关页面实际流动的更多信息,因此您可能需要对其进行调整。

class BaseGame extends React.Component {
    // creating dummy members that get overwritten in concrete game classes
    desc = "";
    id = 0;
    data = {}

    constructor(){
        this.state={
            intro: true,
            success: false,
            fail: false
        }
    }

    /**just dummy functions as we don't have access to
    /*  abstract methods in regular javascript.
    /*
    */
    statusBar(){ return <div>Statusbar</div>}
    gameScreen(){ return <div>the Game Screen</div>}

    render(){
         return (
             {this.statusBar()}
             {if(this.state.intro) <Intro data={this.data} onStart={() => this.setState({intro: false})}/>}
             {if(this.state.success) <Success data={this.data}/>}
             {if(this.state.fail) <Faildata={this.data}/>}
             {if(!this.state.intro && !this.state.fail && !this.state.success) this.gameScreen()} 
         )
    }
}

class Game1 extends BaseGame {
    id = 1;
    data = {GameData}

    // actual implementation of the screens
    statusBar(){ return <div>Game1 StatusBar</div>}
    gameScreen(){ return (
        <div>
            <h1>The UI of Game 1</h1>
            Make sure to setState success or failure at the end of the game loop
        </div>
    )}
}

在应用程序功能中

const App = () => (
 <Router>
    <Switch>
      <Route exact path="/" component={Step1} />
      <Route path="/game1" component={Game1} />
      <Route path="/game2" component={Game2} />
      ...
    </Switch>
  </Router>
)

这只是一个简单的想法。你可能会想添加一个像Redux这样的集中式商店,这取决于你想在哪里管理状态。但是不同的游戏类可以很好地管理它们自己,当它们不需要共享状态时。同样取决于statusBar做什么,它可以在游戏之外,只是在你的应用程序功能中

...
<StatusBar />
<Router>
... etc.
</Router>

在您的应用程序功能。

相关问题