Cannot Read Property 'component' of Undefined Material Ui

React - Cannot read property 'map' of undefined

March 12, 2020 - five min read

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

TypeError: Cannot read property 'map' of undefined

TL;DR - If you are not in the mode for reading or yous simply want the bottom line, so here it is

The trouble

In order to understand what are the possible solutions, lets first understand what is the exact result here.

Consider this code block:

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

Nosotros accept a component that manage a state of items, it also have an event which inside information technology we run an asynchronous operation - getItems, which will return us the data we need from the server, and so nosotros call setItems with the received information every bit items. This component also 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 error:

TypeError: Cannot read property 'map' of undefined

What's going on here?

We practice take an items variable:

                          const              [items,              setItems]              =              useState              (              )              ;                      

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

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

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

  1. React renders (invoking) our component.
  2. React "run into" the useState telephone call and return usa [undefined, fn].
  3. React evaluate our render statement, when it hits the items.map(...) line its actually running undefined.map(...) which is obviously an fault in JavaScript.

What about our useEffect telephone call though?

React will run all effects after the render is committed to the screen, which means nosotros tin't avoid a start return without our data.

Possible solutions

#ane Initial value

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

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

This means that when react runs our useState([]) telephone call, it will return united states with

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

#2 Conditional rendering

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

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

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

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

Annotation that we removed the initial assortment for items.

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

The undefined or null values are ignored inside the context of JSX so its rubber to laissez passer it on for the first return.

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

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

#2.five Inline conditional rendering

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

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

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

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

Nosotros can also use the conditional operator condition ? true : false if we want to render the Loading... text:

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

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

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

Though continue in listen, whenever conditions get too circuitous, it might be a signal for us to excerpt that logic to a component:

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

Wrapping up

When we become such an error, we are probably getting the value in an asynchronous mode. Nosotros should provide an initial value for our variable or conditionally render information technology or both. If our condition become besides circuitous, it might be a practiced time to extract the logic to a component.

Hope yous found this article helpful, if you accept a different approach or any suggestions i would beloved to hear about them, y'all can tweet or DM me @sag1v. 🤓

millerbeirate.blogspot.com

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

0 Response to "Cannot Read Property 'component' of Undefined Material Ui"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel