0

I am facing an issue with having my res value (array) from the getLogs function to be populated to the DataGrid.

UPDATED CODES:

LogDetails.jsx

const columns = [
  { field: "id", headerName: "ID", width: 30 },

  {
    field: "name",
    headerName: "Name",
    width: 250,
  },

  {
    field: "activity",
    headerName: "Activity",
    width: 350,
  },

  {
    field: "date",
    headerName: "Date",
    width: 250,
  },
];

export default function LogDetails() {
  const [logs, setLogs] = useState([]);

  useEffect(() => {
    function logs() {
      getLogs().then((res) => {
        setLogs(res);
      });
    }
    logs();
  }, []);

  return (
    <Box sx={{ width: "100%" }}>
      {logs.length ? (
        <DataGrid
          rows={logs}
          columns={columns}
          pageSize={10}
          rowsPerPageOptions={[10]}
          disableSelectionOnClick
          autoHeight
        />
      ): null}
    </Box>
  );
}

function.js

export async function getLogs() {
  var rows = [];
  const q = query(collection(db, "logs"), orderBy("date", "desc"));
  const docQueury = await getDocs(q);
  var count = 1;
  docQueury.forEach(async (log) => {
    const useref = await getDoc(log.data().user);
    const date = new Timestamp(
      log.data().date.seconds,
      log.data().date.nanoseconds
    )
      .toDate()
      .toLocaleString("en-sg");
    rows.push({
      id: count++,
      name: useref.data().name,
      activity: log.data().activity,
      date: date,
    });
  });
  return rows;
}

Output of "rows" from getLogs function:

rows output from getLogs Function

Output of states from LogDetails.jsx:

enter image description here

UPDATE:

If I were to run the above codes and then delete what is under useEffect(), the data will be populated.

useEffect(() => {

//delete what is under here

}, []);

In addition, I happened to experiment using const rows in the page itself. The data was able to populate successfully to the grid. Thus, right now I suppose it has to do with how my codes under useEffect() has some issue?

const rows = [
  {
    id: 1,
    name: "test",
    activity: "test",
    date: "test"
  }
]
  • 1
    Yes, as far as your given code goes everything is correct, `getLogs` returns an empty array and your setter function `setLogs` passes that value onto your `fetchLogs` state. You should post your `getLogs` code and everything that is affecting it. – Aleksandar Nov 13 '22 at 17:22
  • Why do you use async function without await inside? – Konrad Nov 13 '22 at 17:54
  • Your first log also prints an empty array as you can see it shows `Array(0)`. Clicking an arrow in the dev tools checks the current state of the object, not when it was logged. If you wang to know how it looked like you have to stringify the object – Konrad Nov 13 '22 at 17:55
  • could you show, please, getLogs function? – FD3 Nov 13 '22 at 20:00
  • Hi, sorry just added the getLogs function. @Greg – Kristin Chia Nov 14 '22 at 13:27
  • Thanks for reminding, just added the function code. Hopefully it helps! @Aleksandar – Kristin Chia Nov 14 '22 at 13:32
  • Just FYI, Line 59 runs before your component renders. Line 52 runs AFTER your component renders because it is inside a useEffect hook with an empty dependency array. Checking the state of the component using the React dev tools would probably be a more accurate way to see the value of fetchLogs after render. Also, fetchLogs is not a good variable name for state. It should be [logs, setLogs]. Perhaps the data is there but you have an issue in DataGrid component and it's not rendering correctly? – Neil Girardi Nov 15 '22 at 07:12
  • Just looked at your updated screenshot. It looks like you have an array of six objects stored in the state of your component. – Neil Girardi Nov 15 '22 at 21:08
  • One of the issue that straightforward caught my eye is you are passing `async` callback function inside your `forEach` method which shouldn't happen, you can look up great answers as to why in here: https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop That should single-handedly fix the issue – Aleksandar Nov 16 '22 at 01:47

2 Answers2

0

Since you are fetching the data from an api, in the beginning the fetchLogs will be undefined.
So first you should check if fetchLogs exists and only then populate to the DataGrid.

Update

As you see, you already get the data in getLogs function, you could do this instead. Now, if you console the logs, data should be there. And if still the table is not populated, it means field names don't match.
Also pay attention to naming the functions and variables. Make them more readable.

useEffect(() => {
    const data = getLogs()
      setLogs(data)
  }, []);

 return (
    <Box sx={{ width: "100%" }}>
      {fetchLogs.length>0 && (
        <DataGrid
        rows={fetchLogs}
        columns={columns}
        pageSize={10}
        rowsPerPageOptions={[10]}
        disableSelectionOnClick
        autoHeight
        />
      )}
    </Box>
  );
FD3
  • 1,462
  • 6
  • 24
  • 47
0

The correct way to do the conditional render of the DataGrid would be:

return (
  <Box sx={{ width: "100%" }}>
    {fetchLogs.length ? (
      <DataGrid
        rows={fetchLogs}
        columns={columns}
        pageSize={10}
        rowsPerPageOptions={[10]}
        disableSelectionOnClick
        autoHeight
      />
    ): null}
  </Box>
);

fetchLogs && (<DataGrid/>) will always render the DataGrid because an empty array is "truthy". And fetchLogs.length && (<DataGrid/>) would render 0 when the array is empty.

I'm not sure if this solves the OP's problem but at least it would yield the expected results with regard to conditionally rendering the grid. And as per my previous comment, fetchLogs is not a good name for a state variable. It sounds like a function.

Neil Girardi
  • 4,533
  • 1
  • 28
  • 45
  • Thanks for the suggestion, just updated my post with the necessary changes. Currently, based on the conditional render, it falls on null. – Kristin Chia Nov 15 '22 at 18:16
  • @KristinChia got it. What's happening in the network tab when the data are fetched. Is there an error? – Neil Girardi Nov 15 '22 at 18:54
  • Based on the network tab, there isn't any error. – Kristin Chia Nov 15 '22 at 19:19
  • is it returning data? And if so, if you inspect the LogDetails component with the React dev tools can you see what the state looks like? – Neil Girardi Nov 15 '22 at 19:21
  • Not sure, if I am doing it right but it seems to be returning data? Just updated in my post. – Kristin Chia Nov 15 '22 at 19:33
  • What you want to do is open the developer tools, click on the network tab, and. click "Fetch / XHR". That will show a list of your network requests to your API or backend. Now click on the URL for the request for your logs. Now click the tab that says "Headers" to see the HTTP response code. Now click the "Preview" tab to see the formatted response object. This will tell you if you are getting error codes or success codes, whether or not you're getting data and what the shape of the data is. I hope that helps. – Neil Girardi Nov 15 '22 at 21:06
  • Can you check the value of the columns you are passing to the data grid and make sure they are correct? I am wondering if perhaps you are getting the data but the grid is simply not rendering properly because it doesn't have the right props. – Neil Girardi Nov 15 '22 at 21:22
  • Just updated my value of the columns, I believe they are correct? – Kristin Chia Nov 18 '22 at 13:34