2

I'm trying to get a list of array items from an api response using useEffect, as a result I'm getting a list of objects. I want to convert that using Objects.key() method, but when I iterate through it, values won't be printed on view page. The response keeps on returning the call from api response.

API CALL

 export function getServicesById(facility_id) {     
  return axios
        .get(`${baseURL}patients/appointments/1`)
        .then((response) => {
            if(response.status===200){
                // console.log(response.data)
                return response
            }
        }).catch(error => {
            console.log('error', error)
            return error
        });
    }

useEffect to get response data

  useEffect(() => {
    getServicesById()
      .then((res) => {
        setResponseData(res.data);
      })
      .catch((error) => {
        console.log(error);
      });
    // console.log('data is', newResponseData);
  }, [responseData, setResponseData]);

Converting objects to array items

 const newResponseData = Object.keys(responseData).reduce((array, key) => {
    return [...array, { key: responseData[key] }];
  }, []);

Jsx page where I'm rendering the data

<TableBody>              
  {newResponseData &&
    newResponseData.map((serv, index) => (
    <TableRow key={index}>
       <TableCell align="left" data-label="Action">
           <Field
              name="status"
              component={renderSelectInput}
              variant="outlined"
              size="small"
              className="fileds"
              inputClass="sm-filed"
            >
            <MenuItem selectedValue="progress">
               In progress
             </MenuItem>
             <MenuItem value="closed">
              Closed
             </MenuItem>
            </Field>
            </TableCell>
            <TableCell data-label="Id">{serv.id}</TableCell>
            <TableCell data-label="Patient name">{serv.patient_name}</TableCell>
            <TableCell data-label="Test Name">{serv.test_name}</TableCell>
        </TableRow>
      ))}
   </TableBody>
2
  • You are iterating the mapped newResponseData array. What isn't working? Can you describe that in a bit more detail? Potential issue I see is the mapped objects have only a key key. Commented Mar 12, 2021 at 6:39
  • Values are not displayed on the page, I'm getting a count of table rows with the amount of records I have in db but they are not displayed on the page. Commented Mar 12, 2021 at 6:47

2 Answers 2

1

Issue

You are using an useEffect dependency that the effect updates:

useEffect(() => {
  getServicesById()
    .then((res) => {
      setResponseData(res.data);
    })
    .catch((error) => {
      console.log(error);
    });
}, [responseData, setResponseData]);

responseData is updated by the effect, and when updated will trigger another rerender and the effect will run again. You likely only want to fetch the data once when the component mounts.

Another potential issue I see is that the newResponseData array has objects with only a key key.

const newResponseData = Object.keys(responseData).reduce((array, key) => {
  return [...array, { key: responseData[key] }];
}, []);

But in the render you are attempting to access id, patient_name, and test_name properties. These are undefined since { key: responseData[key] } hasn't any of these properties.

Solution

Remove the useEffect dependencies so the effect runs once on component mount. Since I also think you meant to compute an array of the object values from responseData to map in your UI, you can do this once before sending the data to state.

useEffect(() => {
  getServicesById()
    .then((res) => {
      const data = Object.values(res.data)
      setResponseData(data);
    })
    .catch((error) => {
      console.log(error);
    });
}, []);

Then just map your responseData state:

<TableBody>              
  {responseData && responseData.map((serv, index) => (
    <TableRow key={index}>
       <TableCell align="left" data-label="Action">
           <Field
              name="status"
              component={renderSelectInput}
              variant="outlined"
              size="small"
              className="fileds"
              inputClass="sm-filed"
            >
            <MenuItem selectedValue="progress">
               In progress
             </MenuItem>
             <MenuItem value="closed">
              Closed
             </MenuItem>
            </Field>
            </TableCell>
            <TableCell data-label="Id">{serv.id}</TableCell>
            <TableCell data-label="Patient name">{serv.patient_name}</TableCell>
            <TableCell data-label="Test Name">{serv.test_name}</TableCell>
        </TableRow>
      ))}
   </TableBody>
Sign up to request clarification or add additional context in comments.

Comments

1

In addition to the above answer by Drew Reese, Please remove responseData from useEffect params as you are using setResponseData inside it and useEffect gets triggered on every state change :

useEffect(() => {
    getServicesById()
      .then((res) => {
        setResponseData(res.data);
      })
      .catch((error) => {
        console.log(error);
      });
  }, [setResponseData]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.