Skip to content Skip to sidebar Skip to footer

Schema Cannot Read Property 'latitude' of Undefined

React - Cannot read property 'map' of undefined

March 12, 2020 - 5 min read

If you are a react developer, at that place is a adept run a risk that you lot faced this error couple of times:

TypeError: Cannot read property 'map' of undefined

TL;DR - If you are not in the mode for reading or you just want the bottom line, and then here information technology is

The trouble

In order to understand what are the possible solutions, lets first understand what is the exact issue hither.

Consider this code cake:

                          // Just a data fetching function              const              fetchURL              =              "https://jsonplaceholder.typicode.com/todos/"              ;              const              getItems              =              (              )              =>              fetch              (fetchURL)              .              and so              (              res              =>              res.              json              (              )              )              ;              function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              data              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              render              (                                                <div                >                                                        {items.              map              (              item              =>              (                                                <div                key                                  =                  {item.id}                                >                            {item.title}                                                </div                >                            )              )              }                                                                            </div                >                            )              ;              }                      

We have a component that manage a state of items, information technology also have an effect which inside it we run an asynchronous operation - getItems, which volition return us the data we need from the server, then we call setItems with the received data as items. This component also renders the items - information technology iterate over information technology with .map and returning a react element for each item.

Only we wont see anything on the screen, well except the error:

TypeError: Cannot read holding 'map' of undefined

What's going on here?

We practice have an items variable:

                          const              [items,              setItems]              =              useState              (              )              ;                      

And we did populate it with our data returned from the server:

                          useEffect              (              (              )              =>              {                              getItems                (                )                .                then                (                data                =>                setItems                (data)                )                ;                            }              ,              [              ]              )              ;                      

Well lets examine how the react flow looks similar in our example:

  1. React renders (invoking) our component.
  2. React "run across" the useState call and render the states [undefined, fn].
  3. React evaluate our return statement, when information technology hits the items.map(...) line its actually running undefined.map(...) which is manifestly an error in JavaScript.

What about our useEffect call though?

React will run all furnishings afterward the render is committed to the screen, which means we tin't avoid a first render without our data.

Possible solutions

#1 Initial value

One possible solution is to requite your variable a default initial value, with useState it would expect like that:

                          const              [items,              setItems]              =              useState              (              [              ]              )              ;                      

This means that when react runs our useState([]) telephone call, information technology will return u.s.a. with

Which means that in the first render of our component, react will "see" our items every bit an empty array, so instead of running undefined.map(...) like before, information technology will run [].map(...).

#2 Conditional rendering

Another possible solution is to conditionally render the items, meaning if we have the items then return them, else don't render (or render something else).

When working with JSX we tin can't merely throw some if else statements within our tree:

                          // ⚠️ wont piece of work!!              consign              default              office              App              (              )              {              // ....              return              (                                                <div                >                                                                      {                              if                (items)                {                                            items.                map                (                item                =>                (                                                                                  <div                  cardinal                                      =                    {detail.id}                                    >                                {item.championship}                                                      </div                  >                                                            )                )                                            }                            }                                                                                          </div                >                            )              ;              }                      

Merely instead we can create a variable exterior our tree and populate it conditionally:

Note that nosotros removed the initial array for items.

                          part              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              data              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;                              let                itemsToRender;                                            if                (items)                {                                            itemsToRender                =                items.                map                (                item                =>                {                                            return                                                      <div                  key                                      =                    {item.id}                                    >                                {item.title}                                                      </div                  >                                ;                                            }                )                ;                                            }                                            return                                                      <div                  >                                {itemsToRender}                                                      </div                  >                                ;                            }                      

The undefined or naught values are ignored inside the context of JSX so its safe to pass it on for the outset render.

Nosotros could also utilize an else statement if we desire to render something else like a spinner or some text:

                          function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              data              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              allow              itemsToRender;              if              (items)              {              itemsToRender              =              items.              map              (              item              =>              {              render                                                <div                key                                  =                  {particular.id}                                >                            {particular.title}                                                </div                >                            ;              }              )              ;                              }                else                {                                            itemsToRender                =                "Loading..."                ;                                            }                            return                                                <div                >                            {itemsToRender}                                                </div                >                            ;              }                      

#ii.5 Inline conditional rendering

Another pick to conditionally render something in react, is to use the && logical operator:

                          part              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              information              =>              setItems              (information)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                                                          {items                &&                items.                map                (                item                =>                {                                            return                                                      <div                  key                                      =                    {particular.id}                                    >                                {item.championship}                                                      </div                  >                                ;                                            }                )                }                                                                                                          </div                >                            )              ;              }                      

Why information technology works? The react docs explains it well:

It works because in JavaScript, true && expression always evaluates to expression, and simulated && expression ever evaluates to false. Therefore, if the status is true, the element correct afterwards && will announced in the output. If it is false, React will ignore and skip it.

Nosotros tin can also use the provisional operator condition ? true : faux if we want to render the Loading... text:

                          role              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              data              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                                                          {items                              ?                items.                map                (                item                =>                {                                            return                                                      <div                  central                                      =                    {item.id}                                    >                                {item.title}                                                      </div                  >                                ;                                            }                )                                            :                "Loading..."                }                                                                                                          </div                >                            )              ;              }                      

We tin also mix both solutions, i.eastward: initial value with conditional rendering:

                          function              App              (              )              {                              const                [items,                setItems]                =                useState                (                [                ]                )                ;                            useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              data              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              render              (                                                <div                >                                                                                          {items                &&                items.length                >                0                                            ?                items.                map                (                particular                =>                {                                            render                                                      <div                  key                                      =                    {detail.id}                                    >                                {detail.championship}                                                      </div                  >                                ;                                            }                )                                            :                "Loading..."                }                                                                                                          </div                >                            )              ;              }                      

Though keep in listen, whenever atmospheric condition become too circuitous, information technology might exist a bespeak for us to excerpt that logic to a component:

                                          role                List                (                                  {                  items,                  fallback                  }                                )                {                                            if                (                !items                ||                items.length                ===                0                )                {                                            render                fallback;                                            }                else                {                                            return                items.                map                (                item                =>                {                                            return                                                      <div                  key                                      =                    {particular.id}                                    >                                {item.title}                                                      </div                  >                                ;                                            }                )                ;                                            }                                            }                            function              App              (              )              {              const              [items,              setItems]              =              useState              (              [              ]              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              information              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                                                                                                <                    List                                    items                                      =                    {items}                                    fallback                                      =                    {                    "Loading..."                    }                                    />                                                                                                                          </div                >                            )              ;              }                      

Wrapping up

When we get such an error, we are probably getting the value in an asynchronous way. We should provide an initial value for our variable or conditionally return it or both. If our condition get too complex, it might be a proficient time to excerpt the logic to a component.

Hope yous found this commodity helpful, if you have a different arroyo or any suggestions i would beloved to hear about them, you can tweet or DM me @sag1v. 🤓

mckinnonpritur.blogspot.com

Source: https://www.debuggr.io/react-map-of-undefined/

Post a Comment for "Schema Cannot Read Property 'latitude' of Undefined"