繁体   English   中英

警告:React 检测到 Table 调用的 Hooks 的顺序发生了变化

[英]Warning: React has detected a change in the order of Hooks called by Table

我正在创建一个简单的表,它从 json 收集数据并在表中显示信息。

在表格中,我还为得分超过 100 的人突出显示了背景。 还有一个改变颜色的按钮。

我已经将颜色变化包装为上下文提供者。

当我的表呈现时,我在控制台中收到此错误消息。

react-dom.development.js:51 Warning: React has detected a change in the order of Hooks called by Table. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks

   Previous render            Next render
   ------------------------------------------------------
1. useContext                 useContext
2. useState                   useState
3. useState                   useState
4. useState                   useState
5. useEffect                  useEffect
6. undefined                  useContext
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    at Table (http://localhost:3001/static/js/bundle.js:447:71)
    at ColorContextProvider (http://localhost:3001/static/js/bundle.js:207:5)
    at App

下面是代码:

 import CheckScore from "./checkScore"; import { useEffect, useState } from "react"; import { useColorContext } from "./contexts/Color"; export const Table = () => { const { setHighlightingColor } = useColorContext(); const [users, setUsers] = useState([]); const [total2, setTotal2] = useState(0); const [average2, setAverage2] = useState(0); useEffect(() => { fetch("../players.json").then((r) => r.json()).then((parsedData) => { const totalPoints = parsedData.map((player) => { return player.points; }).reduce((prevValue, curValue) => { return prevValue + curValue; }); setUsers(parsedData); setTotal2(totalPoints); const averagePoints = total2 / parsedData.length; setAverage2(averagePoints); }).catch((err) => { console.log(err); }); }); return ( <> <div className="App-header"> <div> <button onClick={() => setHighlightingColor("red")}>Red</button> <button onClick={() => setHighlightingColor("blue")}>Blue</button> </div> <table> <thead> <tr> <th>Username</th> </tr> <tr> <th>Points</th> </tr> </thead> <tbody> {users.map((e) => CheckScore(e.points, e.username))} <tr> <td>Total</td> <td>{total2}</td> </tr> <tr> <td>Average</td> <td>{average2}</td> </tr> </tbody> </table> </div> </> ); };

和 checkScore 代码

 import { ColorContext } from "./contexts/Color"; import { useContext } from "react"; export default function CheckScore(score, player) { const { highlightingColor } = useContext(ColorContext); return ( <tr key={player} className={`${score > 100? highlightingColor: ""} `}> <td>{player}</td> <td>{score}</td> </tr> ); }

和颜色上下文

 import { useState, createContext, useContext } from "react"; export const ColorContext = createContext("red"); export const ColorContextProvider = ({ children }) => { const [highlightingColor, setHighlightingColor] = useState("red"); return ( <ColorContext.Provider value={{ highlightingColor, setHighlightingColor }}> {children} </ColorContext.Provider> ); }; export const useColorContext = () => useContext(ColorContext);

任何想法我做错了什么?

TL;DR:问题是您在CheckScore useContext中调用了 useContext。

无论哪种方式都会解决:

  1. highlightingColor作为参数传递给CheckScore函数,并且不要在其中调用useContext
  2. {users.map((e) => <CheckScore score={e.points} player={e.username} />)}并将function CheckScore(score, player)的参数更改为function CheckScore({ score, player })

解释

您需要明确区分 a)“反应功能组件”和 b)“返回反应元素的 function”。

CheckScore仅在作为<CheckScore />调用时才有资格作为功能组件。 你调用它的方式,作为一个正常的 function,取消它作为组件的资格,因此useContext调用被认为是在<Table />组件的生命周期内调用的。

users数发生变化时, useContext调用的次数也会发生变化。 正如https://reactjs.org/link/rules-of-hooks中所建议的那样,这段代码会造成麻烦。

===

以下是我在您的代码中发现的错误。 与您当前的问题无关,但值得注意。 这是修复它的方法。 我发布为答案,因为我无法在评论中获得正确的格式。

    setTotal2(totalPoints);
    - const averagePoints = total2 / parsedData.length;
    + const averagePoints = totalPoints / parsedData.length;
    setAverage2(averagePoints);

在您计算averagePoints时, total2 != totalPoints 您应该改用totalPoints 原因是setState更新是异步的,所以total2直到下一次渲染才更新。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM