Cannot Read Property 'playerpic' of Undefined Angular 4

React - Cannot read belongings 'map' of undefined

March 12, 2020 - 5 min read

If you are a react developer, there is a good adventure that you lot faced this error couple of times:

TypeError: Cannot read property 'map' of undefined

TL;DR - If yous are not in the style for reading or y'all just want the bottom line, then here information technology is

The trouble

In club to understand what are the possible solutions, lets first understand what is the verbal outcome here.

Consider this code cake:

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

Nosotros have a component that manage a state of items, it also have an consequence which inside it we run an asynchronous operation - getItems, which will return the states the data we need from the server, so we call setItems with the received data every bit items. This component likewise renders the items - information technology iterate over it with .map and returning a react chemical element for each item.

Just we wont see anything on the screen, well except the fault:

TypeError: Cannot read property 'map' of undefined

What's going on hither?

We do 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 menstruum looks like in our example:

  1. React renders (invoking) our component.
  2. React "see" the useState call and render us [undefined, fn].
  3. React evaluate our render statement, when it hits the items.map(...) line its really running undefined.map(...) which is plainly an error in JavaScript.

What near our useEffect telephone call though?

React volition run all effects after the render is committed to the screen, which means we can't avoid a kickoff 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 like that:

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

This means that when react runs our useState([]) telephone call, it will render us with

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

#2 Provisional rendering

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

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

                          // ⚠️ wont work!!              export              default              part              App              (              )              {              // ....              render              (                                                <div                >                                                                      {                              if                (items)                {                                            items.                map                (                item                =>                (                                                                                  <div                  fundamental                                      =                    {item.id}                                    >                                {detail.championship}                                                      </div                  >                                                            )                )                                            }                            }                                                                                          </div                >                            )              ;              }                      

Merely instead we can create a variable outside our tree and populate information technology conditionally:

Note that we removed the initial array for items.

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

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

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

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

#2.5 Inline conditional rendering

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

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

Why it works? The react docs explains it well:

It works because in JavaScript, true && expression e'er evaluates to expression, and false && expression always evaluates to imitation. Therefore, if the condition is true, the element right after && volition appear in the output. If information technology is false, React will ignore and skip it.

We can as well utilise the conditional operator status ? true : false if nosotros desire to return the Loading... text:

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

Nosotros tin as well mix both solutions, i.east: initial value with conditional rendering:

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

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

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

Wrapping up

When we become such an fault, 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 become too complex, information technology might be a good time to extract the logic to a component.

Hope y'all plant this commodity helpful, if you accept a different approach or any suggestions i would honey to hear most them, you lot can tweet or DM me @sag1v. 🤓

mcfarlandflosse.blogspot.com

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

0 Response to "Cannot Read Property 'playerpic' of Undefined Angular 4"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel