Tablesorter Cannot Read Property 'pager' of Undefined

React - Cannot read property 'map' of undefined

March 12, 2020 - 5 min read

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

TypeError: Cannot read property 'map' of undefined

TL;DR - If you lot are not in the mode for reading or you lot just desire the bottom line, then here information technology is

The problem

In order to empathise what are the possible solutions, lets start empathize what is the exact event here.

Consider this code cake:

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

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

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

TypeError: Cannot read property 'map' of undefined

What'southward going on here?

We do have an items variable:

                          const              [items,              setItems]              =              useState              (              )              ;                      

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

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

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

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

What near our useEffect telephone call though?

React will run all effects later the return is committed to the screen, which means we can't avoid a first render without our information.

Possible solutions

#one Initial value

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

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

This means that when react runs our useState([]) call, it will render us with

Which means that in the outset render of our component, react will "see" our items equally an empty array, so instead of running undefined.map(...) like before, it will run [].map(...).

#2 Conditional rendering

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

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

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

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

Note that nosotros removed the initial array for items.

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

The undefined or null values are ignored inside the context of JSX then its safety to pass it on for the first render.

Nosotros could also apply an else statement if we want to return something else similar a spinner or some text:

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

#2.5 Inline conditional rendering

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

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

Why it works? The react docs explains it well:

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

We can also use the provisional operator condition ? true : false if we want to return the Loading... text:

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

We can too mix both solutions, i.eastward: initial value with conditional rendering:

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

Though continue in mind, whenever conditions become as well complex, information technology might be a betoken for us to extract that logic to a component:

                                          function                List                (                                  {                  items,                  fallback                  }                                )                {                                            if                (                !items                ||                items.length                ===                0                )                {                                            return                fallback;                                            }                else                {                                            return                items.                map                (                particular                =>                {                                            return                                                      <div                  key                                      =                    {item.id}                                    >                                {detail.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 mistake, nosotros are probably getting the value in an asynchronous manner. We should provide an initial value for our variable or conditionally render it or both. If our condition become also complex, information technology might be a good fourth dimension to excerpt the logic to a component.

Hope yous institute this article helpful, if you take a different approach or any suggestions i would love to hear nigh them, you can tweet or DM me @sag1v. 🤓

healytherose.blogspot.com

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

0 Response to "Tablesorter Cannot Read Property 'pager' of Undefined"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel