Javascript 使用React钩子,如果其中一个';s的兄弟姐妹改变状态?

Javascript 使用React钩子,如果其中一个';s的兄弟姐妹改变状态?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我已经使用array.map创建了一个组件网格。使用console.log我可以看到,每当一个组件改变状态时,每个组件都在重新渲染。当网格为50x50时,速度会明显变慢 import React, { useState } from 'react'; function Cell({ cell, cellState, updateBoard }) { console.log('cell rendered') const CellStyle = { display: 'inli

我已经使用array.map创建了一个组件网格。使用
console.log
我可以看到,每当一个组件改变状态时,每个组件都在重新渲染。当网格为50x50时,速度会明显变慢

import React, { useState } from 'react';

function Cell({ cell, cellState, updateBoard }) {

  console.log('cell rendered')

  const CellStyle = {
    display: 'inline-block',
    width: '10px',
    height: '10px',
    border: '1px green solid',
    background: cellState ? 'green' : 'purple'
  };

  function handleClick(e) {
    updateBoard(cell, !cellState)
  }

  return (
    <span
      style={CellStyle}
      onClick={handleClick}
    />
  )
}

function App() {

  console.log('board rendered')

  const initialState = new Array(10).fill().map(() => new Array(10).fill(false));

  let [board, setBoard] = useState(initialState);

  function updateBoard(cell, nextState) {
    let tempBoard = [...board];
    tempBoard[cell[0]][cell[1]] = nextState;
    setBoard(tempBoard)
  }

  return (
    <div style={{ display: 'inline-block' }}>
      {board.map((v, i, a) => {
        return (
          <div
            key={`Row${i}`}
            style={{ height: '12px' }}
          >
            {v.map((w, j) =>
              <Cell
                key={`${i}-${j}`}
                cell={[i, j]}
                cellState={board[i][j]}
                updateBoard={updateBoard}
              />
            )}
          </div>
        )
      }
      )}
    </div>
  )
}

export default App;
import React,{useState}来自“React”;
功能单元({Cell,cellState,updateBoard}){
console.log('cell rendered')
常量单元格样式={
显示:“内联块”,
宽度:“10px”,
高度:“10px”,
边框:“1px绿色实心”,
背景:cellState?“绿色”:“紫色”
};
函数handleClick(e){
更新板(单元格,!单元格状态)
}
返回(
)
}
函数App(){
console.log('board rendered')
const initialState=new Array(10.fill().map(()=>new Array(10.fill)(false));
let[board,setBoard]=使用状态(初始状态);
功能更新板(单元格,下一状态){
让tempBoard=[…board];
tempBoard[cell[0]][cell[1]]=nextState;
立根板(临时板)
}
返回(
{board.map((v,i,a)=>{
返回(
{v.map((w,j)=>
)}
)
}
)}
)
}
导出默认应用程序;

单击其中一个组件时,我希望父状态更新,单击的组件更新并重新渲染。由于其余组件没有更改,因此我不希望其他组件重新渲染。如何使用React钩子实现这一点?

有几件事可以大大提高性能:

  • 使用
    memo()
  • 您正在创建
    initialState
    每个渲染-将其移动到上方(外部)
    或在内部创建
    useState
    作为函数(并使用
    const
    而不是
    let

  • 最终解决方案:

    import React, { useState, memo, useCallback } from "react";
    import ReactDOM from "react-dom";
    
    function Cell({ i, j, cellState, updateBoard }) {
      console.log(`cell ${i}, ${j} rendered`);
    
      const CellStyle = {
        display: "inline-block",
        width: "10px",
        height: "10px",
        border: "1px green solid",
        background: cellState ? "green" : "purple"
      };
    
      function handleClick(e) {
        updateBoard([i, j], !cellState);
      }
    
      return <span style={CellStyle} onClick={handleClick} />;
    }
    
    const MemoizedCell = memo(Cell);
    
    function App() {
      console.log("board rendered");
    
      const [board, setBoard] = useState(() =>
        new Array(10).fill().map(() => new Array(10).fill(false))
      );
    
      const updateBoard = useCallback(
        (cell, nextState) => {
          setBoard(oldBoard => {
            let tempBoard = [...oldBoard];
            tempBoard[cell[0]][cell[1]] = nextState;
            return tempBoard;
          });
        },
        [setBoard]
      );
    
      return (
        <div style={{ display: "inline-block" }}>
          {board.map((v, i, a) => {
            return (
              <div key={`Row${i}`} style={{ height: "12px" }}>
                {v.map((w, j) => (
                  <MemoizedCell
                    key={`${i}-${j}`}
                    i={i}
                    j={j}
                    cellState={board[i][j]}
                    updateBoard={updateBoard}
                  />
                ))}
              </div>
            );
          })}
        </div>
      );
    }
    
    export default App;
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    
    import React,{useState,memo,useCallback}来自“React”;
    从“react dom”导入react dom;
    功能单元({i,j,cellState,updateBoard}){
    log(`cell${i},${j}rendered`);
    常量单元格样式={
    显示:“内联块”,
    宽度:“10px”,
    高度:“10px”,
    边框:“1px绿色实心”,
    背景:cellState?“绿色”:“紫色”
    };
    函数handleClick(e){
    更新板([i,j],!cellState);
    }
    返回;
    }
    常量MemoizedCell=备忘录(单元格);
    函数App(){
    console.log(“提交的董事会”);
    const[board,setBoard]=useState(()=>
    新数组(10.fill().map(()=>新数组(10.fill)(false))
    );
    const updateBoard=useCallback(
    (单元格,下一个状态)=>{
    立根板(旧板=>{
    让tempBoard=[…oldBoard];
    tempBoard[cell[0]][cell[1]]=nextState;
    返回临时板;
    });
    },
    [黑板]
    );
    返回(
    {board.map((v,i,a)=>{
    返回(
    {v.map((w,j)=>(
    ))}
    );
    })}
    );
    }
    导出默认应用程序;
    const rootElement=document.getElementById(“根”);
    render(,rootElement);
    
    您是否也知道如何消除eslint错误,该错误抱怨缺少依赖项
    board
    ('react-hooks/deps')@hyde您可以在
    const updateBoard
    中添加
    board
    作为
    [board,setBoard]
    中添加
    board
    。我更新了我的答案-现在它应该在
    eslint
    中正确验证。这确实有助于消除关于useCallback和useMemo的许多混淆,从而提高性能。
      const updateBoard = useCallback(
        (cell, nextState) => {
          setBoard(oldBoard => {
            let tempBoard = [...oldBoard];
            tempBoard[cell[0]][cell[1]] = nextState;
            return tempBoard;
          });
        },
        [setBoard]
      );
    
    const [board, setBoard] = useState(() =>
      new Array(10).fill().map(() => new Array(10).fill(false))
    );
    
    import React, { useState, memo, useCallback } from "react";
    import ReactDOM from "react-dom";
    
    function Cell({ i, j, cellState, updateBoard }) {
      console.log(`cell ${i}, ${j} rendered`);
    
      const CellStyle = {
        display: "inline-block",
        width: "10px",
        height: "10px",
        border: "1px green solid",
        background: cellState ? "green" : "purple"
      };
    
      function handleClick(e) {
        updateBoard([i, j], !cellState);
      }
    
      return <span style={CellStyle} onClick={handleClick} />;
    }
    
    const MemoizedCell = memo(Cell);
    
    function App() {
      console.log("board rendered");
    
      const [board, setBoard] = useState(() =>
        new Array(10).fill().map(() => new Array(10).fill(false))
      );
    
      const updateBoard = useCallback(
        (cell, nextState) => {
          setBoard(oldBoard => {
            let tempBoard = [...oldBoard];
            tempBoard[cell[0]][cell[1]] = nextState;
            return tempBoard;
          });
        },
        [setBoard]
      );
    
      return (
        <div style={{ display: "inline-block" }}>
          {board.map((v, i, a) => {
            return (
              <div key={`Row${i}`} style={{ height: "12px" }}>
                {v.map((w, j) => (
                  <MemoizedCell
                    key={`${i}-${j}`}
                    i={i}
                    j={j}
                    cellState={board[i][j]}
                    updateBoard={updateBoard}
                  />
                ))}
              </div>
            );
          })}
        </div>
      );
    }
    
    export default App;
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);