![](/img/trans.png)
[英]Getting the error " React has detected a change in the order of Hooks called by StudentsFilter"
[英]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。
无论哪种方式都会解决:
highlightingColor
作为参数传递给CheckScore
函数,并且不要在其中调用useContext
。{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.