Fully Initiate Your State To Make React Render Your Data More Easily
Published: 2023-01-07 06:14:39

One thing I learned (a few times) over the past few weeks is what to do to do when React gives an (unexpected) undefined error for no apparent reason about heavily nested state objects.  A simple .map method being attempted on a an array returns something like: 

TypeError: Cannot read properties of undefined (reading ‘map’)

A troubleshooting observation of my console log results: the array would be initiated with   some of the important values (my IDs and foreign_ids) would initiate as strings.  And the console would log these items not just twice as React often does, but sometimes three, four or even six times before the expected values would finally populate instead of the empty strings I initiated the nested state objects with.

Sadly this happened to me quite a few times with other methods and functions as well as simple renders.  Even more odd, sometimes when I would I have the app open in my browser, the data would render in my component right after saving but a page refresh would return the error.  So in summary, I knew the syntax was likely NOT the issue as it render on the page momentarily.  The data was getting from point A to B (turns out it had to also stop at C, D, E and more in React).

A couple unsuccessful solutions I also tried:

1. Moving the state to a higher level component and passing it as a prop, nope
2. Trying to render with callbacks in higher level components, exact same issues
3. Changing the database to have some of the objects be slightly less nested, sometimes but not always

The conclusion I came to was that React didn’t know the exact data type of my state when I initiated it.  I had:

1. An array of objects
2. With nested objects
3. And nested arrays of objects
4. All with multiple data types
5. And some integers initiated as strings

So trying to be as efficient as possible I would enter just enough information of the objects that would allow React to .map it to render it.  And this would fix the problem until I moved to the next feature.  So more specific I would get on the nested objects expected data.  Here is what my final useState array of objects looked like so that all of my features would render:

```
const [trips, setTrips] = useState([{
    id: 0,
    user_id: 0,
    mountain_id: 0,
    trip_start: "2022-10-15T18:30:00.000Z",
    trip_end: "2022-10-15T18:30:00.000Z",
    comments: [],
    mountain: {},
    users: [{
        id: 0,
        username: "",
        first_name: "",
        last_name: "",
        email: "",
        avatar: "",
        age: 0,
        neighborhood: "",
        admin: false,

    }],
    user_trips: [{
        id: 0,
        user_id: 0,
        trip_id: 0,
        user: {
            id: 0,
            username: "",
            first_name: "",
            last_name: "",
            email: "",
            avatar: "",
            age: 0,
            neighborhood: "",
            admin: false,
        }
    }],
  }]);
```

So in summary my recommendations:
 

1. Fully list all of the objects (and arrays and arrays of objects) inside of your state
2. Make sure you initiate with the correct data type too (no strings when an integer will be used for  IDs!)

Most likely the why, per my understanding, is that React has to make multiple passes through the data and functions before it fully renders in your app.  It makes initial allocations for the data, then looks at all the functions, then attempts to process the functions with some of the data provided, then iterates through all of this until it finally returns the result to the allocated memory allocation.  

And when the data is nested heavily and the data types are not fully defined it takes many passes before the data gets allocated.  React will (in my case here and on other projects I have worked on) just throw an error essentially saying: I can’t map through your array because I have not had a chance to put the data there yet to map through it.

Hopefully if you are struggling with the same mysteries this will help send you in the right direction to get that data rendered!