Cannot Read Property '_root' of Undefined React Native Native Bsae

React - Cannot read property 'map' of undefined

March 12, 2020 - 5 min read

If y'all are a react programmer, there is a good chance that you 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 lesser line, then here it is

The problem

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

Consider this code block:

                          // Simply a data fetching office              const              fetchURL              =              "https://jsonplaceholder.typicode.com/todos/"              ;              const              getItems              =              (              )              =>              fetch              (fetchURL)              .              then              (              res              =>              res.              json              (              )              )              ;              part              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              information              =>              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 upshot which inside it we run an asynchronous operation - getItems, which will return usa the data we need from the server, then we call setItems with the received data as items. This component as well renders the items - it iterate over it with .map and returning a react element for each item.

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

TypeError: Cannot read belongings 'map' of undefined

What's going on hither?

We practise have an items variable:

                          const              [items,              setItems]              =              useState              (              )              ;                      

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

                          useEffect              (              (              )              =>              {                              getItems                (                )                .                then                (                data                =>                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 call and return us [undefined, fn].
  3. React evaluate our render statement, when information technology hits the items.map(...) line its really running undefined.map(...) which is obviously an error in JavaScript.

What almost our useEffect phone call though?

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

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

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

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

#2 Conditional rendering

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

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

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

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

Note that we removed the initial assortment for items.

                          function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              information              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;                              let                itemsToRender;                                            if                (items)                {                                            itemsToRender                =                items.                map                (                detail                =>                {                                            render                                                      <div                  primal                                      =                    {item.id}                                    >                                {item.championship}                                                      </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 starting time render.

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

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

#2.5 Inline conditional rendering

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

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

Why it works? The react docs explains it well:

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

Nosotros tin can also utilise the conditional operator status ? true : fake if nosotros want to render the Loading... text:

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

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

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

Though proceed in heed, whenever weather become likewise circuitous, information technology might be a signal for u.s. to extract that logic to a component:

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

Wrapping upwardly

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 become besides complex, it might be a good time to extract the logic to a component.

Promise you constitute this article helpful, if yous accept a unlike arroyo or whatsoever suggestions i would love to hear about them, you tin can tweet or DM me @sag1v. 🤓

diazvareat36.blogspot.com

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

0 Response to "Cannot Read Property '_root' of Undefined React Native Native Bsae"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel