Typeerror Cannot Read Property 'navigate' of Undefined React Native

React - Cannot read property 'map' of undefined

March 12, 2020 - five min read

If you are a react developer, there is a expert risk that you faced this error couple of times:

TypeError: Cannot read holding 'map' of undefined

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

The problem

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

Consider this code block:

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

We have a component that manage a state of items, information technology as well accept an result which inside it we run an asynchronous performance - getItems, which will return the states the data we demand from the server, then we call setItems with the received data as items. This component also renders the items - it iterate over information technology with .map and returning a react chemical element for each item.

Merely we wont see annihilation on the screen, well except the error:

TypeError: Cannot read holding 'map' of undefined

What'due south going on here?

We practice have an items variable:

                          const              [items,              setItems]              =              useState              (              )              ;                      

And nosotros did populate it with our information returned from the server:

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

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

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

What about our useEffect call though?

React will run all effects afterward the return is committed to the screen, which means nosotros can't avert a get-go render without our data.

Possible solutions

#1 Initial value

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

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

This ways that when react runs our useState([]) telephone call, information technology will return us with

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

#2 Conditional rendering

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

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

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

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

Notation that we removed the initial array for items.

                          function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              and then              (              information              =>              setItems              (information)              )              ;              }              ,              [              ]              )              ;                              let                itemsToRender;                                            if                (items)                {                                            itemsToRender                =                items.                map                (                item                =>                {                                            return                                                      <div                  cardinal                                      =                    {particular.id}                                    >                                {item.title}                                                      </div                  >                                ;                                            }                )                ;                                            }                                            render                                                      <div                  >                                {itemsToRender}                                                      </div                  >                                ;                            }                      

The undefined or cypher values are ignored inside the context of JSX so its condom to laissez passer it on for the starting time return.

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

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

#2.5 Inline conditional rendering

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

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

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

It works considering in JavaScript, true && expression e'er evaluates to expression, and simulated && expression always evaluates to false. Therefore, if the status is true, the element correct after && will appear in the output. If information technology is false, React will ignore and skip it.

We tin can also use the conditional operator condition ? true : false if nosotros want to render the Loading... text:

                          function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              and so              (              data              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                                                          {items                              ?                items.                map                (                particular                =>                {                                            return                                                      <div                  central                                      =                    {particular.id}                                    >                                {item.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              (              )              .              then              (              data              =>              setItems              (information)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                                                          {items                &&                items.length                >                0                                            ?                items.                map                (                item                =>                {                                            return                                                      <div                  key                                      =                    {particular.id}                                    >                                {item.title}                                                      </div                  >                                ;                                            }                )                                            :                "Loading..."                }                                                                                                          </div                >                            )              ;              }                      

Though keep in heed, whenever weather condition become too complex, it might be a bespeak for us to extract that logic to a component:

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

Wrapping up

When nosotros get such an error, nosotros are probably getting the value in an asynchronous way. We should provide an initial value for our variable or conditionally render it or both. If our condition go too complex, information technology might be a good time to extract the logic to a component.

Hope you lot establish this article helpful, if you have a dissimilar approach or whatever suggestions i would dearest to hear about them, y'all can tweet or DM me @sag1v. 🤓

coombseved1972.blogspot.com

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

0 Response to "Typeerror Cannot Read Property 'navigate' of Undefined React Native"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel