Home > front end >  using api to call users and material ui data grid to show users
using api to call users and material ui data grid to show users

Time:02-04

i am working on an application that I make API calls to get some users for an id. the API gives you the users in an object of 25 length, and i order to get the other users u have to make other API calls.

I have a parent component from which I look for users and I pass down some variables to my child component:

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

then in my child component I am using the material ui data grid as follows:

  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]);

and this is how I try to fetch users based on page number:

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

so I set my users here which I want to use on data model.

and also

  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>
          </>
        );
      },
    },
  ];

this is how I make my model:

<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 }))
  }
/>

the problem is that I load users but I wont be able to show them inside my model

here u can see:enter image description here

I am loading 25 users but the model doesn't show anything, however it shows me 1–25 of 5101 when i click on > I can load the users on my model like but now I am on 26–50 of 5101 so I am in page 2 but I am showing the data for page 1, when i click on > again I can see that this works but I am always behinds the correct page and sometimes Im in page 6 but I am still seeing data for page 2, and I can see that model is not being updated correctly.

on my dependency on my useEffect I have [rowsState.page, rowsState.pageSize], while the enter image description here

CodePudding user response:

There's a lot going on here, and I think your component is overall too complex. If you try and simplify things you might make it easier to see the problem.

First, I'd move the fetchAllUsers out to a separate method - it doesn't need to use state, it can just be a simple wrapper around an API call. Also, given that it's fetching a subset of users, it should probably not be called "fetchAllUsers". And, you're mixing async/await with promises - just stick with using async/await. Something like this might work

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

I'd also suggest you encapsulate the loading of the paged data into a separate hook. This article does a good job of explaining why you should use custom hooks for encapsulation. Your effect also has a dependency on the props.id which looks like it's a campaign id. Again, something like this might work - there's a few red flags in there which I've commented in the code below:

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
    }
}

Now your component that contains the data grid can use your custom hook as follows:

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