Home > database >  React Hook useState Is Returning Undefined
React Hook useState Is Returning Undefined

Time:05-24

I am trying to fill a table with data from an API.

 const [GetSimIDs, setGetSimIDs] = React.useState(); 

    // Using useEffect to call the API once mounted and set the data
    useEffect(() => {
      window.harmxy.api
        .invokeProxy(
          "/sit/issues?sort=createDate desc&q=status:(Open) containingFolder:(aaaa-b5b9-4829-8b87-489053f9bb42)",
          {
            method: "GET",
            stage: "corp",
            headers: {
              "Content-Type": "application/json",
            },
          }
        ) //api finishes here
        .then((xhr) => {
          //response is captured here
          //var SIMID = JSON.parse(xhr.response).id;
          console.log(xhr.responseText);
          const data = JSON.parse(xhr.response);
          //const data = xhr.response;
          console.log(data);
          console.log(data.totalNumberFound);
          setGetSimIDs(data);
        });
    }, []);

The state GetSimIDs is updated successfully with data like this:

{
  "documents": [
    {
      "assignedFolder": "4a37-416c-8531-",
      "extensions": {
        "tt": {
          "impact": 5,
          "category": "EiC",
          "type": "IBug",
          "item": "Macro",
          "assignedGroup": "EiC",
          "justification": [],
          "minImpact": 5,
          "status": "Assd"
        }
      },
      "watchers": [
        { "id": "[email protected]", "type": "email" },
        { "id": "[email protected]", "type": "email" },
        { "id": "[email protected]", "type": "email" },
        { "id": "[email protected]", "type": "email" }
      ],
      "customFields": {
        "number": [{ "id": "fte_saving", "value": 0 }],
        "date": [
          { "id": "delivery_date", "value": "2022-05-17T15:43:49.825Z" }
        ],
        "string": [
          { "id": "category_of_the_request", "value": "Other" },
          { "id": "region_of_impact", "value": "NA" },
          { "id": "tool_type", "value": "Excel Macro" },
          {
            "id": "impacted_tool",
            "value": "Tickets Helper"
          }
        ]
      }
     
    },
    {
      "title": "Issue or Bug - Global Wizard - NA",
      "assignedFolder": "416c-8531-37fa3a701712",
      
      "watchers": [{ "id": "[email protected]", "type": "email" }],
      "customFields": {
        "number": [{ "id": "fte_saving", "value": 0 }],
        "date": [
          { "id": "delivery_date", "value": "2022-05-13T02:22:46.751Z" }
        ],
        "string": [
          { "id": "category_of_the_request", "value": "Other" },
          { "id": "region_of_impact", "value": "NA" },
          { "id": "tool_type", "value": "Excel Macro" },
          { "id": "impacted_tool", "value": "Global Wizard" }
        ]
      }
      
    }
  ],
  "totalNumberFound": 2,
  "searchLogMessages": [],
  "startToken": ""
}

So I tried to update the table with the following code:

<tbody>
                <tr>
                  <th>title</th>
                  <th>Id</th>
                  <th>status</th>
                </tr>
                {GetSimIDs.map((documents, i) => (
                  <tr key={i}>
                    <td>{documents.title}</td>
                    <td>{documents.id}</td>
                    <td>{documents.status}</td>
                  </tr>
                ))}
              </tbody>

But I keep getting an error in line

{GetSimIDs.map((documents, i) => ( 

Saying that TypeError: s is undefined

Any idea as of why it seems not getting the data from the hook?

I am very new to react so all feedback would be appreciated.

Thanks Luis V.

CodePudding user response:

This is a common problem with async data. The state is initially undefined, and is filled in later after the request has completed. There will always be at least one render before your data is loaded.

You can fix this in several ways, but the simplest would be to just initialize the state to an empty array:

const [GetSimIDs, setGetSimIDs] = React.useState([]);

Now the state is always defined, and you can map over it even before the data is loaded.

Another option would be to check the data before mapping it:

{GetSimIDs && GetSimIDs.map((documents, i) => (

CodePudding user response:

Data returned from the API seems to be an object with a property documents which is an array. Either you can

setGetSimIDs(data.documents)

OR

GetSimIDs.documents.map(...)

Update (Codesandbox): Seems you're also missing a few null checks due to which there are errors. Initially the object array are empty so we can't use the map function. Only when data has successfully loaded we can render the rows.

I have used your data set & made a mock api.

export default function App() {
  const [GetSimIDs, setGetSimIDs] = useState([]);

  useEffect(() => {
    axios
      .get("https://getsimids.free.beeceptor.com/my/api/path")
      .then((res) => {
        setGetSimIDs(res.data);
      });
  }, []);
  return (
    <div className="App">
      <table>
        <tbody>
          <tr>
            <th>title</th>
            <th>Id</th>
            <th>status</th>
          </tr>
          {GetSimIDs.documents &&
            GetSimIDs.documents.length > 0 &&
            GetSimIDs.documents.map((documents, i) => (
              <tr key={i}>
                <td>{documents.title}</td>
                <td>{documents.id}</td>
                <td>{documents.status}</td>
              </tr>
            ))}
        </tbody>
      </table>
    </div>
  );
}

CodePudding user response:

Can you log the value of GetSimIDs and GetSimIDs before the map function.

console.log(GetSimIDs, GetSimIDs.documents)
GetSimIDs.map...

Also set the const [GetSimIDs, setGetSimIDs] = React.useState([]); instead of empty

  • Related