Okta Sign in Cannot Read Property 'renderel' of Undefined

React - Cannot read property 'map' of undefined

March 12, 2020 - 5 min read

If you lot are a react programmer, at that place is a good chance that you faced this error couple of times:

TypeError: Cannot read holding 'map' of undefined

TL;DR - If you are not in the mode for reading or y'all just want the bottom line, then here it is

The problem

In order to empathize what are the possible solutions, lets first understand what is the verbal issue here.

Consider this code block:

                          // 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              (              )              .              and so              (              information              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                        {items.              map              (              item              =>              (                                                <div                fundamental                                  =                  {item.id}                                >                            {item.title}                                                </div                >                            )              )              }                                                                            </div                >                            )              ;              }                      

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

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

TypeError: Cannot read property 'map' of undefined

What'due south going on hither?

We do accept an items variable:

                          const              [items,              setItems]              =              useState              (              )              ;                      

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

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

Well lets examine how the react menstruation looks like in our example:

  1. React renders (invoking) our component.
  2. React "run across" the useState call and return us [undefined, fn].
  3. React evaluate our return argument, when it hits the items.map(...) line its actually running undefined.map(...) which is patently an error in JavaScript.

What nigh our useEffect telephone call though?

React will run all effects later the render is committed to the screen, which means we can't avoid a outset render without our data.

Possible solutions

#1 Initial value

One possible solution is to give your variable a default initial value, with useState it would look similar that:

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

This means that when react runs our useState([]) call, it volition return usa with

Which means that in the first render of our component, react will "encounter" our items equally an empty array, then instead of running undefined.map(...) like before, it volition run [].map(...).

#two Conditional rendering

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

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

                          // ⚠️ wont work!!              consign              default              role              App              (              )              {              // ....              return              (                                                <div                >                                                                      {                              if                (items)                {                                            items.                map                (                particular                =>                (                                                                                  <div                  key                                      =                    {item.id}                                    >                                {particular.title}                                                      </div                  >                                                            )                )                                            }                            }                                                                                          </div                >                            )              ;              }                      

But instead we can create a variable outside our tree and populate it conditionally:

Note that we removed the initial array for items.

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

The undefined or zero values are ignored within the context of JSX then its safe to pass information technology on for the first render.

We could also use an else statement if nosotros want to return something else like a spinner or some text:

                          role              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              data              =>              setItems              (information)              )              ;              }              ,              [              ]              )              ;              let              itemsToRender;              if              (items)              {              itemsToRender              =              items.              map              (              item              =>              {              return                                                <div                cardinal                                  =                  {particular.id}                                >                            {item.championship}                                                </div                >                            ;              }              )              ;                              }                else                {                                            itemsToRender                =                "Loading..."                ;                                            }                            return                                                <div                >                            {itemsToRender}                                                </div                >                            ;              }                      

#2.5 Inline conditional rendering

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

                          office              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              and so              (              data              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                                                          {items                &&                items.                map                (                detail                =>                {                                            return                                                      <div                  primal                                      =                    {item.id}                                    >                                {item.title}                                                      </div                  >                                ;                                            }                )                }                                                                                                          </div                >                            )              ;              }                      

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

It works because in JavaScript, truthful && expression always evaluates to expression, and false && expression always evaluates to false. Therefore, if the condition is true, the element correct subsequently && will appear in the output. If it is imitation, React volition ignore and skip it.

We tin besides use the conditional operator condition ? true : imitation 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                  key                                      =                    {item.id}                                    >                                {particular.title}                                                      </div                  >                                ;                                            }                )                                            :                "Loading..."                }                                                                                                          </div                >                            )              ;              }                      

Nosotros can also mix both solutions, i.e: initial value with provisional rendering:

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

Though keep in mind, whenever weather become too complex, information technology might be a signal for us to extract that logic to a component:

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

Wrapping up

When we get such an error, we are probably getting the value in an asynchronous manner. We should provide an initial value for our variable or conditionally render it or both. If our status become as well complex, it might be a skilful time to extract the logic to a component.

Promise yous plant this article helpful, if you lot have a different arroyo or any suggestions i would love to hear near them, you can tweet or DM me @sag1v. 🤓

parkerknowerfe.blogspot.com

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

Related Posts

0 Response to "Okta Sign in Cannot Read Property 'renderel' of Undefined"

Postar um comentário

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel