Jira Tempo Uncaught Typeerror: Cannot Read Property 'foreach' of Undefined

React - Cannot read property 'map' of undefined

March 12, 2020 - 5 min read

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

TypeError: Cannot read belongings 'map' of undefined

TL;DR - If you are not in the mode for reading or yous simply want the lesser line, then here information technology is

The problem

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

Consider this code block:

                          // Just a data fetching role              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              (information)              )              ;              }              ,              [              ]              )              ;              render              (                                                <div                >                                                        {items.              map              (              item              =>              (                                                <div                key                                  =                  {item.id}                                >                            {particular.title}                                                </div                >                            )              )              }                                                                            </div                >                            )              ;              }                      

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

Merely we wont see anything on the screen, well except the mistake:

TypeError: Cannot read property 'map' of undefined

What's going on here?

We do have an items variable:

                          const              [items,              setItems]              =              useState              (              )              ;                      

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

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

Well lets examine how the react menses looks like in our instance:

  1. React renders (invoking) our component.
  2. React "see" the useState phone 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 nigh our useEffect phone call though?

React will run all furnishings after the render is committed to the screen, which ways we tin can't avert a first return 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 us with

Which means that in the first render of our component, react will "see" our items equally an empty array, and so instead of running undefined.map(...) like earlier, information technology volition run [].map(...).

#2 Conditional rendering

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

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

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

But instead nosotros 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              (information)              )              ;              }              ,              [              ]              )              ;                              allow                itemsToRender;                                            if                (items)                {                                            itemsToRender                =                items.                map                (                item                =>                {                                            return                                                      <div                  key                                      =                    {item.id}                                    >                                {particular.title}                                                      </div                  >                                ;                                            }                )                ;                                            }                                            return                                                      <div                  >                                {itemsToRender}                                                      </div                  >                                ;                            }                      

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

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

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

#2.five Inline provisional rendering

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

                          function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              and then              (              data              =>              setItems              (information)              )              ;              }              ,              [              ]              )              ;              render              (                                                <div                >                                                                                          {items                &&                items.                map                (                particular                =>                {                                            return                                                      <div                  primal                                      =                    {particular.id}                                    >                                {particular.championship}                                                      </div                  >                                ;                                            }                )                }                                                                                                          </div                >                            )              ;              }                      

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

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

We can likewise apply the provisional operator condition ? true : false if we desire to render the Loading... text:

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

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

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

Though keep in mind, whenever conditions become too complex, information technology might be a bespeak for u.s.a. to excerpt that logic to a component:

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

Wrapping up

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

Promise y'all found this commodity helpful, if you have a different arroyo or any suggestions i would dear to hear virtually them, yous can tweet or DM me @sag1v. 🤓

kennedymushmers.blogspot.com

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

0 Response to "Jira Tempo Uncaught Typeerror: Cannot Read Property 'foreach' of Undefined"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel