代码之家  ›  专栏  ›  技术社区  ›  Josh Simon

如何让组件“侦听”同级组件中全局状态的更改?

  •  0
  • Josh Simon  · 技术社区  · 2 年前

    我正在构建wordle克隆。我将其构造为键盘和字母显示网格是两个独立的组件, Keypad.js Row,js 分别地项目结构如下:

    src
    -components
     |-Grid.js
     |-Keypad.js
     |-Row.js
    -App.js
    -AppContex.js
    -index.js
    

    当用户在键盘上输入字母时,最初我希望该字母出现在第一行的第一个索引中,就像wordle游戏一样。我如何获得 Row.js “倾听”中的变化 键盘。js公司 ,这样当用户输入一个字母时,它会显示在网格行的相应索引中?

    到目前为止,我的方法是使用上下文API创建全局状态,我在其中创建了一个空网格以共享给整个应用程序:

    AppContext。js公司

    import { createContext } from "react";
    
    const guessRows = [
        ['', '', '', '', ''],
        ['', '', '', '', ''],
        ['', '', '', '', ''],
        ['', '', '', '', ''],
        ['', '', '', '', ''],
        ['', '', '', '', '']
    ]
    
    export const AppContext = createContext()
    
    const AppContextProvider = (props) => {
        return(
            <AppContext.Provider value = {guessRows}>
                {props.children}
            </AppContext.Provider>
        )
    }
    
    export default AppContextProvider
    

    在里面 键盘。js公司 ,用户输入的字母用于更新上下文(或者至少我认为它是这样做的):

    import { useContext,useState } from "react"
    import { AppContext } from "../AppContext"
    
    const Keypad = () => {
      const guessRows = useContext(AppContext);
      let currentRow = 0;
      let currentTile = 0;
    
      const letters = [
        "Q",
        "W",
        "E",
        "R",
       // etc
      ];
    
      const handleClick = (letter) => {
        guessRows[currentRow][currentTile] = letter;
        currentTile++;
        console.log("guess rows", guessRows);
      };
    
      return (
        <div className="keyboard-container">
          {letters.map((letter, index) => {
            return (
              <div className="key" key={index} onClick={() => handleClick(letter)}>
                {letter}
              </div>
            );
          })}
        </div>
      );
    };
     
    export default Keypad;
    

    ...然后在 一行js公司 ,我在上下文中循环并呈现行:

    一行js公司

    import { useContext } from "react";
    import { AppContext } from "../AppContext";
    
    
    const Row = () => {
    
      const rowData = useContext(AppContext)
      const currentRow = rowData[0]
    
      return (
        <div className="row">
          {currentRow.map((letter,index) => {
            return(
              <div className="tile" id = {index}>{letter}</div>
            )
          })}
        </div>
      )
    }
     
    export default Row;
    

    不出所料,这是行不通的,所以任何建议都将不胜感激。

    1 回复  |  直到 2 年前
        1
  •  1
  •   CertainPerformance    2 年前

    你的 guessRows 应该放在上下文状态中,这样就可以传递状态设置器,而不是 guessRows[currentRow][currentTile] = letter; ,调用状态设置器。同样地, currentTile++; 应替换为状态更新,因为这是React-视图应来自状态。

    const AppContextProvider = (props) => {
        const [guessRows, setGuessRows] = useState([
            ['', '', '', '', ''],
            ['', '', '', '', ''],
            ['', '', '', '', ''],
            ['', '', '', '', ''],
            ['', '', '', '', ''],
            ['', '', '', '', '']
        ]);
        return(
            <AppContext.Provider value = {{ guessRows, setGuessRows }}>
                {props.children}
            </AppContext.Provider>
        );
    };
    
    const { guessRows, setGuessRows } = useContext(AppContext);
    const [currentRow, setCurrentRow] = useState(0);
    const [currentTile, setCurrentTile] = useState(0);
    
    const handleClick = (letter) => {
        setGuessRows(
            guessRows.map((row, i) => i !== currentRow ? row : (
                row.map((item, j) => j === currentTile ? letter : item)
            ))
        );
        setCurrentTile(currentTile + 1);
    };
    

    然后,当调用状态设置器时,组件将重新呈现,包括行,这将显示所做的更改。