Vm19947:61 Typeerror: Cannot Read Property 'get' of Undefined

React - Cannot read holding 'map' of undefined

March 12, 2020 - 5 min read

If you are a react developer, there is a expert chance that y'all faced this mistake couple of times:

TypeError: Cannot read belongings 'map' of undefined

TL;DR - If yous are not in the style for reading or you just desire the lesser line, then here information technology is

The trouble

In social club to empathise what are the possible solutions, lets first empathise what is the exact issue here.

Consider this code cake:

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

We take a component that manage a land of items, it too have an effect which inside it we run an asynchronous operation - getItems, which will return united states of america the data nosotros need from the server, then we call setItems with the received data every bit items. This component likewise renders the items - it iterate over it with .map and returning a react chemical element for each item.

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

TypeError: Cannot read belongings 'map' of undefined

What'southward going on here?

We do have an items variable:

                          const              [items,              setItems]              =              useState              (              )              ;                      

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

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

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

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

What about our useEffect call though?

React will run all furnishings after the render is committed to the screen, which means we tin't avert a starting time render without our information.

Possible solutions

#1 Initial value

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

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

This ways that when react runs our useState([]) phone call, it volition return us with

Which means that in the kickoff return of our component, react volition "see" our items as an empty assortment, so instead of running undefined.map(...) similar before, it will run [].map(...).

#ii Conditional rendering

Another possible solution is to conditionally return the items, pregnant if nosotros take the items so return them, else don't render (or render something else).

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

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

Simply instead we tin create a variable outside our tree and populate it conditionally:

Note that we removed the initial array for items.

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

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

We could as well use an else statement if we desire to return something else like a spinner or some text:

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

#2.five Inline provisional rendering

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

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

Why it works? The react docs explains information technology 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 right after && volition appear in the output. If it is imitation, React will ignore and skip information technology.

We tin also use the conditional operator condition ? true : false if nosotros desire to return the Loading... text:

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

Nosotros can also mix both solutions, i.east: initial value with conditional rendering:

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

Though keep in listen, whenever atmospheric condition become too circuitous, it might exist a signal for us to extract that logic to a component:

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

Wrapping upwards

When nosotros go such an error, we are probably getting the value in an asynchronous style. Nosotros should provide an initial value for our variable or conditionally return it or both. If our condition become besides complex, information technology might exist a good time to extract the logic to a component.

Promise you lot establish this article helpful, if y'all have a different approach or any suggestions i would dear to hear about them, you can tweet or DM me @sag1v. 🤓

leblanchantivane.blogspot.com

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

0 Response to "Vm19947:61 Typeerror: Cannot Read Property 'get' of Undefined"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel