首页 > 解决方案 > React useHook 导致我的 API 后端进入无限循环

问题描述

我有一个我想不通的问题。

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

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

<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' }
    });
};

该按钮有效,它正在更新系统和数据库中的正确属性,更新状态,并在删除适当行的情况下静默更新表格,但它将后端 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']

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

表中数据的状态管理如下:

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;

“修复”是,在 React.useEffect 钩子中的 [data] 中取出“数据”。

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

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

谢谢!:)

标签: reactjsentity-framework-corereact-hooksreact-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
}

推荐阅读