我怎样才能更好地有条件地渲染我的组件?

Posted

技术标签:

【中文标题】我怎样才能更好地有条件地渲染我的组件?【英文标题】:How can I better conditionally render my components? 【发布时间】:2022-01-12 05:25:58 【问题描述】:

我有很多组件根据我用于游戏的不同状态进行渲染。我目前正在使用用 & 号检查状态值的方法。我不确定是否应该采用其他方式,或者是否有更有效的清洁方式。

我已经查找了几种不同的方法,但想知道是否有人可以给我一些建议,让我可以很好地与我现有的代码一起工作。

const App = () => 
  const [startPlayer, setStartPlayer] = useState("");
  const [endPlayer, setEndPlayer] = useState("");
  const [gameSelected, setGameSelected] = useState(false);
  const [gameStarted, setGameStarted] = useState(false);
  const [gameWon, setGameWon] = useState(false);
  const [winningTeam, setWinningTeam] = useState([]);
  const [gameSolved, setGameSolved] = useState(false);
  const isMobile = useMobileCheck();  

  const resetGame = () => 
    setStartPlayer("");
    setEndPlayer("");
    setGameSelected(false);
    setGameStarted(false);
    setGameWon(false);
    setGameSolved(false);
    setWinningTeam([]);
  ;
  
  const setGameType = (gameType) => 
    setGameSelected(gameType);
  ;
  
  const rollPlayers = (startYear, endYear) => 
    axios.get(`/api/gettwoplayers?startYear=$startYear&endYear=$endYear`).then((res) => 
      setStartPlayer(res.data[0]);
      setEndPlayer(res.data[1]);
    );
  ;
  
  const startTheGame = () =>     
    setGameStarted(true);
  ;

  const goBackToGameSelection = () => 
    setGameSelected(false);
    setGameStarted(false);
    setStartPlayer("");
    setEndPlayer("");
  ;

  const userSetPlayer = (player, type) => 
    if(type === "start") setStartPlayer(player);
    if(type === "end") setEndPlayer(player);
  ;

  const theGameWasWon = (history) => 
    history.push(endPlayer);
    setWinningTeam(history);
    setGameWon(true);
  ;

  const solveGame = () => 
    setGameSolved(true);
    axios.get(`/api/solve?startPlayer=$startPlayer&endPlayer=$endPlayer`).then((res) => 
      console.log(res.data);
    )
  ;

  return (
    <Container
      sx=
        minHeight:'100vh',        
        maxWidth: "90vw!important",
      
    >
      
        !gameSelected &&
        !gameStarted &&
        !gameWon &&
        <ChooseGame setGameType=setGameType />
      

      
        !gameStarted &&
        !gameWon &&
        gameSelected === 'r' &&   
        <CreateRandomGame 
          rollPlayers=rollPlayers 
          startPlayer=startPlayer 
          endPlayer=endPlayer
          startTheGame=startTheGame
          goBack=goBackToGameSelection
        />
      

      
        !gameStarted &&
        !gameWon &&  
        gameSelected === 's' &&
        <CreateUserGame
          startPlayer=startPlayer
          endPlayer=endPlayer
          userSetPlayer=userSetPlayer
          startTheGame=startTheGame
          goBack=goBackToGameSelection
        />
      
      
      
        !gameWon &&
        gameStarted &&
        <GameScreen 
          startPlayer=startPlayer
          endPlayer=endPlayer
          gameWon=theGameWasWon
          resetGame=resetGame
          solveGame=solveGame
        />
      

      
        gameWon &&
        <GameWon 
          resetGame=resetGame
          winningTeam=winningTeam
        />
      
    </Container>
  );


export default App;

【问题讨论】:

你可以使用三元运算符来解决一些简单的情况 【参考方案1】:

你可以尝试两件事:

首先,您有很多 boolean 状态 - 例如。 gameStarted,其中很多似乎与 other 布尔状态互斥,例如 gameStarted 看起来像它永远不可能同时是 true作为gameWon。在这种情况下,将状态建模为枚举类型会好得多。不幸的是,javascript 本身并没有它们(查看 TypeScript 以获得“真实”enum 类型)但我们可以使用字符串:

const MODE_STARTED = 'started'
const MODE_SELECTED_RANDOM = 'random'
const MODE_SELECTED_USER = 'user'
const MODE_GAME_WON = 'won'
...
const [gameMode, setGameMode] = useState(MODE_STARTED);
...

现在,您无需在各处翻转单个布尔值,只需更改游戏模式...例如setGameMode(MODE_SELECTED_RANDOM)

一旦你这样做了,你的 JSX 也会变得更干净:

const showCorrectUI = () => 
  switch (gameMode) 
    case MODE_STARTED:
      return <GameScreen foo />
    case MODE_GAME_WON:
      return <GameWon bar />
     ... // etc
  


return (
  <Container
    sx=
      minHeight:'100vh',        
      maxWidth: "90vw!important",
    
  >
    showCorrectUI()
  </Container>)

【讨论】:

所以我正在尝试这个,它在渲染新组件时调用我的 setgamestate 函数。例如case RANDOM_GAME_SELECTED: return &lt;CreateRandomGame rollPlayers=rollPlayers startPlayer=startPlayer endPlayer=endPlayer startTheGame=changeGameState goBack=changeGameState /&gt;;它渲染这段代码,然后为startTheGamegoBack调用changeGameState,因为当我记录它时,它会以不同的状态运行该函数三次。 我想通了,它们是 onclick 函数,我需要做 onClick=() =&gt; goBack("GAME_CHOICE") 它必须有带箭头函数的括号

以上是关于我怎样才能更好地有条件地渲染我的组件?的主要内容,如果未能解决你的问题,请参考以下文章

React:我怎样才能让这个 React 组件写得更好更高效?

React:组件和数组的条件渲染

如何根据 prop 有条件地渲染组件的颜色?

有条件地渲染同一个组件不会触发挂载()钩子。

根据功能组件中的数据有条件地渲染元素

根据 selectOneMenu 值有条件地渲染组件