Typeerror Cannot Read Property 'map' of Undefined Jest React
                      
React - Cannot read property 'map' of undefined
March 12, 2020 - 5 min read
If you are a react programmer, in that location is a good take chances that yous 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 you simply want the bottom line, then hither information technology is
The trouble
In order to understand what are the possible solutions, lets first sympathize what is the exact issue hither.
Consider this lawmaking block:
                          // Just a data fetching part              const              fetchURL              =              "https://jsonplaceholder.typicode.com/todos/"              ;              const              getItems              =              (              )              =>              fetch              (fetchURL)              .              then              (              res              =>              res.              json              (              )              )              ;              function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              information              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                        {items.              map              (              particular              =>              (                                                <div                primal                                  =                  {item.id}                                >                            {item.title}                                                </div                >                            )              )              }                                                                            </div                >                            )              ;              }                              We have a component that manage a state of          items, it too have an effect which inside it we run an          asynchronous          performance -          getItems, which volition return us the          data          we need from the server, and then we telephone call          setItems          with the received data as          items. This component also renders the          items          - it iterate over it with          .map          and returning a react element for each item.
Just we wont see anything on the screen, well except the mistake:
TypeError: Cannot read property 'map' of undefined
What'southward going on hither?
Nosotros do take an          items          variable:
                          const              [items,              setItems]              =              useState              (              )              ;                              And we did populate it with our information returned from the server:
                          useEffect              (              (              )              =>              {                              getItems                (                )                .                and so                (                information                =>                setItems                (information)                )                ;                            }              ,              [              ]              )              ;                              Well lets examine how the react period looks like in our example:
- React renders (invoking) our component.
 - React "see" the            
useStatephone call and return us[undefined, fn]. - React evaluate our render statement, when information technology hits the            
items.map(...)line its really runningundefined.map(...)which is patently an error in JavaScript. 
What about our          useEffect          telephone call though?
React will run all effects after the render is committed to the screen, which ways we can't avoid a showtime render without our data.
Possible solutions
#ane Initial value
One possible solution is to give your variable a default initial value, with          useState          information technology would look like that:
                          const              [items,              setItems]              =              useState              (              [              ]              )              ;                              This means that when react runs our          useState([])          call, information technology will return us with
Which means that in the first render of our component, react will "see" our          items          as 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, meaning          if          we have the items then render them,          else          don't render (or render something else).
When working with          JSX          we can't merely throw some          if          else          statements within our tree:
                          // ⚠️ wont piece of work!!              consign              default              role              App              (              )              {              // ....              return              (                                                <div                >                                                                      {                              if                (items)                {                                            items.                map                (                particular                =>                (                                                                                  <div                  key                                      =                    {detail.id}                                    >                                {item.championship}                                                      </div                  >                                                            )                )                                            }                            }                                                                                          </div                >                            )              ;              }                              But instead we tin create a variable outside our tree and populate it conditionally:
          Annotation that we removed the initial array for            items.        
                          function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              data              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;                              let                itemsToRender;                                            if                (items)                {                                            itemsToRender                =                items.                map                (                item                =>                {                                            return                                                      <div                  key                                      =                    {item.id}                                    >                                {detail.championship}                                                      </div                  >                                ;                                            }                )                ;                                            }                                            render                                                      <div                  >                                {itemsToRender}                                                      </div                  >                                ;                            }                              The          undefined          or          null          values are ignored inside the context of          JSX          so its prophylactic to pass it on for the outset return.
We could as well use an          else          statement if we desire to return something else similar a spinner or some text:
                          function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              data              =>              setItems              (information)              )              ;              }              ,              [              ]              )              ;              let              itemsToRender;              if              (items)              {              itemsToRender              =              items.              map              (              particular              =>              {              return                                                <div                central                                  =                  {item.id}                                >                            {detail.title}                                                </div                >                            ;              }              )              ;                              }                else                {                                            itemsToRender                =                "Loading..."                ;                                            }                            return                                                <div                >                            {itemsToRender}                                                </div                >                            ;              }                              #2.5 Inline conditional rendering
Another pick to conditionally render something in react, is to apply 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.championship}                                                      </div                  >                                ;                                            }                )                }                                                                                                          </div                >                            )              ;              }                              Why it works? The react docs explains it well:
It works because in JavaScript, true && expression e'er evaluates to expression, and imitation && expression always evaluates to fake. Therefore, if the condition is true, the element correct after && volition announced in the output. If it is faux, React will ignore and skip it.
Nosotros tin also utilise the conditional operator          condition ? true : imitation          if we want to render the          Loading...          text:
                          function              App              (              )              {              const              [items,              setItems]              =              useState              (              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              information              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                                                          {items                              ?                items.                map                (                particular                =>                {                                            render                                                      <div                  key                                      =                    {item.id}                                    >                                {item.title}                                                      </div                  >                                ;                                            }                )                                            :                "Loading..."                }                                                                                                          </div                >                            )              ;              }                              We can also mix both solutions, i.due east: initial value with conditional rendering:
                          role              App              (              )              {                              const                [items,                setItems]                =                useState                (                [                ]                )                ;                            useEffect              (              (              )              =>              {              getItems              (              )              .              and then              (              information              =>              setItems              (data)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                                                          {items                &&                items.length                >                0                                            ?                items.                map                (                item                =>                {                                            render                                                      <div                  key                                      =                    {item.id}                                    >                                {item.championship}                                                      </div                  >                                ;                                            }                )                                            :                "Loading..."                }                                                                                                          </div                >                            )              ;              }                              Though keep in mind, whenever conditions become besides complex, it might be a signal for the states to extract that logic to a component:
                                          part                Listing                (                                  {                  items,                  fallback                  }                                )                {                                            if                (                !items                ||                items.length                ===                0                )                {                                            return                fallback;                                            }                else                {                                            return                items.                map                (                item                =>                {                                            render                                                      <div                  key                                      =                    {particular.id}                                    >                                {item.title}                                                      </div                  >                                ;                                            }                )                ;                                            }                                            }                            part              App              (              )              {              const              [items,              setItems]              =              useState              (              [              ]              )              ;              useEffect              (              (              )              =>              {              getItems              (              )              .              then              (              data              =>              setItems              (information)              )              ;              }              ,              [              ]              )              ;              return              (                                                <div                >                                                                                                                                <                    Listing                                    items                                      =                    {items}                                    fallback                                      =                    {                    "Loading..."                    }                                    />                                                                                                                          </div                >                            )              ;              }                              Wrapping up
When nosotros get such an fault, 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 get as well circuitous, it might be a expert time to excerpt the logic to a component.
Hope y'all found this commodity helpful, if you accept a dissimilar approach or whatever suggestions i would dearest to hear nigh them, you lot can tweet or DM me @sag1v. 🤓
phillipsristraid1999.blogspot.com
Source: https://www.debuggr.io/react-map-of-undefined/
0 Response to "Typeerror Cannot Read Property 'map' of Undefined Jest React"
Post a Comment