使用 api 调用用户并使用 material ui 数据网格显示用户

using api to call users and material ui data grid to show users

我正在开发一个应用程序,我会调用 API 来获取一些用户的 ID。 API 为您提供 25 长度的对象中的用户,我为了让其他用户必须进行其他 API 调用。

我有一个父组件,我从中查找用户并将一些变量传递给我的子组件:

<UserSection
                    id={id}
                    code={code}
                    open={open}
                    users={users}
                    setOpen={setOpen}
                    handleClose={handleClose}
                    handleUsers={handleUsers}
                    total={total}
                    currentPageNr={currentPageNr}
                    maxPageNr={maxPageNr}
                  />

然后在我的子组件中,我使用 material ui 数据网格,如下所示:

  const [rowsState, setRowsState] = React.useState({
    page: 0,
    pageSize: 25,
    rows: [],
    loading: false,
  });



const rows = [];

  useEffect(() => {
    let active = true;

    (async () => {
      setRowsState((prev) => ({ ...prev, loading: true }));
      await fetchAllUsers(rowsState.page);

      for (let i = 0; i < users.length; i++) {
        if (users[i].campaign_id == props.id) {
          let row = {
            id: i + 1,
            col1: i + 1,
            col2: users[i].id,
            col3: users[i].first_name,
            col4: users[i].qualified,
            col5: users[i].email,
            col6: users[i].source,
            col7: users[i].referrer_id,
            col8: showName(users[i].referrer_id),
            // col9: props.users[i].url,
            col10: justSHowReached(users[i].id),
            col11: users.filter(
              (u) => u.referrer_id == users[i].id && u.qualified
            ).length,
            col12: changeDate(users[i].date),
            // col13: "",
          };
          rows[i] = row;
        }
      }

      const newRows = rows;

      console.log("new rows:", newRows);
      console.log("eowsState.page:", rowsState.page);
      // console.log("===**=== rowsState.pageSize:", rowsState.pageSize);

      if (!active) {
        return;
      }
      setRowsState((prev) => ({ ...prev, loading: false, rows: newRows }));
    })();

    return () => {
      active = false;
    };
  }, [rowsState.page, rowsState.pageSize]);

这就是我尝试根据页码获取用户的方式:

const fetchAllUsers = async (pageNumber) => {
    console.log("----------------------------------");
    console.log("page number: ", pageNumber);
    console.log("----------------------------------");
    await fetch(
      `........./api/v1/users?page=${pageNumber}`,
      {
        method: "GET",
        headers: new Headers({
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        }),
      }
    )
      .then((res) => res.json())
      .then(async (data) => {
        // console.log("=================rows=================");
        setUsers(data.data);
        return data.data;
      })
      .catch((error) => {
        console.log(error);
      });
  };

所以我在这里设置了我想在数据模型上使用的用户。

还有

  const columns = [
    { field: "col1", headerName: "#", width: 50 },
    { field: "col2", headerName: "Id", width: 100, sortable: false },
    { field: "col3", headerName: "Name", width: 100 },
    { field: "col4", headerName: "Qualified", width: 100 },
    { field: "col5", headerName: "Email", width: 200 },
    { field: "col6", headerName: "Source", width: 75 },
    { field: "col7", headerName: "Referrer Id", width: 125 },
    { field: "col8", headerName: "Referrer Name", width: 125 },
    // { field: "col9", headerName: "Url", width: 300 },
    {
      field: "col10",
      headerName: "Reached",
      width: 150,
    
    },
    { field: "col11", headerName: "Qualified", width: 150 },
    { field: "col12", headerName: "Date Created", width: 150 },
    {
      field: "col13",
      headerName: "Action",
      width: 150,
      sortable: false,
      filterable: false,
      hideable: false,

      renderCell: (params) => {
        const onClick = (e) => {
          e.stopPropagation(); // don't select this row after clicking

          const api = params.api;
          const thisRow = {};

          api
            .getAllColumns()
            .filter((c) => c.field !== "__check__" && !!c)
            .forEach(
              (c) => (thisRow[c.field] = params.getValue(params.id, c.field))
            );

          console.log("---->", thisRow.col2, thisRow.col4);

          setUserId(thisRow.col2);
          updateUser(thisRow.col2, thisRow.col4);
          //   return alert(JSON.stringify(thisRow, null, 4));
        };

        return (
          <>
            <Button variant="contained" onClick={onClick}>
              update
            </Button>
          </>
        );
      },
    },
  ];

这就是我制作模型的方式:

<DataGrid
  // rows={rows}
  columns={columns}
  pagination
  rowCount={props.total}
  paginationMode="server"
  // pageSize={25}
  rowsPerPageOptions={[25]}
  {...rowsState}
  onPageChange={(page) => {
    // console.log("and page is ", page);
    setRowsState((prev) => ({ ...prev, page }));
  }}
  onPageSizeChange={(pageSize) =>
    setRowsState((prev) => ({ ...prev, pageSize }))
  }
/>

问题是我加载了用户,但我无法在我的模型中显示他们

在这里你可以看到:

我正在加载 25 个用户,但模型没有显示任何内容,但是当我单击 > 时它显示 1–25 of 5101 我可以在我的模型上加载用户,但现在我是在 26–50 of 5101 上,所以我在第 2 页,但我显示的是第 1 页的数据,当我再次单击 > 时,我可以看到这是有效的,但我总是落后于正确的页面,有时我在第 6 页,但我仍然看到第 2 页的数据,并且我可以看到模型未正确更新。

关于我对 useEffect 的依赖,我有 [rowsState.page, rowsState.pageSize],toturial says 我需要有 3 个,第 3 个是行,如果我把用户放在那里,应用程序将继续渲染,最终 firefox 将崩溃。我如何确保我为每个页面获取正确的数据以及如何将数据直接加载到模型?

这里发生了很多事情,我认为您的组件总体上太复杂了。如果您尝试简化事情,您可能会更容易发现问题。

首先,我将 fetchAllUsers 移到一个单独的方法中 - 它不需要使用状态,它可以只是一个围绕 API 调用的简单包装器。此外,鉴于它正在获取用户的一个子集,它可能不应该被称为“fetchAllUsers”。而且,您将 async/await 与 promises 混合在一起 - 只需坚持使用 async/await。这样的事情可能会奏效

const fetchUsersForPage = async (pageNumber) => {
    try {
        const response = await fetch(
        // Copied from your code but looks very suspicious...
        `........./api/v1/users?page=${pageNumber}`,
        {
            method: "GET",
            headers: new Headers({
                "Content-Type": "application/json",
                Authorization: `Bearer ${token}`,
            }),
        });

        const { data } = await response.json();
        return data;

    } catch (error) {
        console.log(error);
    }
};

我还建议您将分页数据的加载封装到一个单独的挂钩中。 This article does a good job of explaining why you should use custom hooks for encapsulation。您的效果还依赖于 props.id,它看起来像是一个广告系列 ID。同样,这样的事情可能会起作用——我在下面的代码中评论了一些危险信号:

const usePagedData = (campaignId, page, pageSize) => {
    const [loading, setLoading] = useState(false);
    const [rows, setRows] = useState([]);

    useEffect(() => {
        const loadPageData = async () => {
            setLoading(true);

            const users = await fetchUsersForPage(page);

            const userRows = users
                // This looks suspicious - you might be losing users because they
                // don't match the campaign? Shouldn't you pass the campaignId
                // as part of the fetch in that case?
                .filter(user => user.campaign_id === campaignId)
                .map((user, index) => ({
                    id: index + 1,
                    col1: index + 1,
                    col2: user.id,
                    col3: user.first_name,
                    col4: user.qualified,
                    col5: user.email,
                    col6: user.source,
                    col7: user.referrer_id,

                    // Not sure what these functions are??
                    col8: showName(user.referrer_id),
                    // col9: props.users[i].url,
                    col10: justSHowReached(user.id),

                    // This number will almost certainly be wrong since 'users' is
                    // the list of users for this page.
                    col11: users.filter(u => u.referrer_id == user.id && u.qualified).length,
                    col12: changeDate(user.date),
                    // col13: "",
                  }));
            
            setRows(userRows);      
        }

        loadPageData();
    }, [campaignId, page, pageSize]);

    return {
        rows,
        loading
    }
}

现在您的包含数据网格的组件可以使用您的自定义挂钩,如下所示:

const { rows, loading } = usePagedData(props.id, page, pageSize);