React useHook 导致我的 API 后端进入无限循环

React useHook is causing my API backend to go into an endless loop

我有一个问题无法解决。

我在前端使用 React,后端使用 .NetCore 3.1 Entity Framework。

在我的一个 React 组件中,我有一个按钮,可以从 table 中的游戏列表中删除游戏。

<Button variant="success" onClick={() => deleteFromList(row.original)}>Publish</Button>&nbsp;&nbsp;&nbsp;

点击后,执行这段代码:

// when the button clicked, this calls 'updateGame' method
const deleteFromList = (e) => {
    updateGame(e, 1);
}


// updateGame submits a PUT request to the API
const updateGame = async (game, action) => {
    game.isGamePublished = action;
    await axios({
        method: "PUT",
        url: "api/games/" + game.id,
        data: JSON.stringify(game),
        headers: { 'Content-Type': 'application/json; charset=utf-8' }
    });
};

按钮有效,它正在更新系统和数据库中的正确 属性,状态已更新,并且 table 会静默更新并删除适当的行,但它会发送后端 API 进入这个无限循环,它一遍又一遍地显示这个输出:

输出:

SELECT [d].[name]
FROM [genre] AS [d]
Microsoft.EntityFrameworkCore.Database.Command Information: Executed DbCommand (2ms) [Parameters=[@__isGamePublished_0='?' (DbType = Boolean)], CommandType='Text', CommandTimeout='30']
SELECT [p].[id], [p].[title], .[url], [d].[name]
FROM [game] AS [p]
INNER JOIN [genre] AS [d] ON [p].[deptId] = [d].[id]
INNER JOIN [author] AS [m] ON [p].[authorId] = [m].[id]
INNER JOIN [type] AS [t] ON [p].[typeId] = [t].[id]
LEFT JOIN [gameAuthors] AS [p0] ON [p].[id] = [p0].[gameId]
WHERE [p].[isGamePublished] = @__isGamePublished_0

Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor: Information: Executing ObjectResult, writing value of type 'System.Collections.Generic.List`1[[ART_Game.Models.GameEntity, ART_Game, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'.
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Executed action ART_Game.Controllers.GamesController.GetGame (ART_Game) in 10.3631ms
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint 'ART_Game.Controllers.GamesController.GetGame (ART_Game)'
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 18.3252ms 200 application/json; charset=utf-8
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 GET https://localhost:44376/api/games/?isGamePublished=false  
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'ART_Game.Controllers.GamesController.GetGame (ART_Game)'
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action = "GetGame", controller = "Games"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.ActionResult`1[System.Collections.Generic.List`1[ART_Game.Models.GameEntity]]] GetGame(Boolean) on controller ART_Game.Controllers.GamesController (ART_Game).
Microsoft.EntityFrameworkCore.Infrastructure: Information: Entity Framework Core 3.1.2 initialized 'ARTGamesContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
Microsoft.EntityFrameworkCore.Database.Command: Information: Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']

我确实找到了一个 "fix" 但它并不是真正的修复,因为它阻止了我的 React 组件的反应。

table中数据的状态是这样管理的:

const [data, setData] = React.useState([]);
React.useEffect(() => {
    gameData(false).then(res => {
        setData(res.data);
    });
}, [data]);

gameData is just a simple Axios fetch component that submits a get request to my Entity Framework API:

const gameData = async isPublished) => {
   const result = await axios("api/games/", {
      params: {
        isGamePublished: isPublished
      }
   });
  return result;
};

export default gameData;

"fix"就是,把React.useEffect钩子里"data"这里的[数据]取出来。

但这会阻止 React 组件从 table 中动态删除游戏...相反,用户需要刷新网页才能看到新结果。

我想知道是否有人见过这样的事情并且知道如何正确修复它?

谢谢! :)

此处的解决方案是仅在与 table 交互时重新获取数据。您可以从服务器获取数据,也可以根据未选择的行自行从状态中删除项目。

下面是从服务器获取数据的方法。

const [data, setData] = React.useState([]);

const fetchAndUpdate = useCallback(() => {
   gameData(false).then(res => {
        setData(res.data);
    });
}, [])

React.useEffect(() => {
    fetchAndUpdate()
}, []);


// when the button clicked, this calls 'updateGame' method
const deleteFromList = async (e) => {
    await updateGame(e, 1);
    fetchAndUpdate(); // fetch data and update state
}