Do not name a React serve as part

Do not name a React serve as part

[ad_1]

Watch “Repair ‘React Error: Rendered fewer hooks than anticipated'” on egghead.io

I were given an excellent query from Taranveer Bains
on my AMA asking:

I bumped into a topic the place if I equipped a serve as that used hooks in its
implementation and returned some JSX to the callback for
Array.prototype.map. The mistake I gained used to be
React Error: Rendered fewer hooks than anticipated.

Here is a easy replica of that error

import * as React from 'react'

serve as Counter() {
  const [count, setCount] = React.useState(0)
  const increment = () => setCount(c => c + 1)
  go back <button onClick={increment}>{rely}</button>
}

serve as App() {
  const [items, setItems] = React.useState([])
  const addItem = () => setItems(i => [...i, {id: i.length}])
  go back (
    <div>
      <button onClick={addItem}>Upload Merchandise</button>
      <div>{pieces.map(Counter)}</div>
    </div>
  )
}

And here is how that behaves when rendered (with an error boundary round it so
we do not crash this web page):

Within the console, there are extra main points in a message like this:

Caution: React has detected a transformation within the order of Hooks
referred to as through BadCounterList. This may result in insects and
mistakes if now not mounted. For more info, learn the
Laws of Hooks: https://facebook.me/rules-of-hooks

   Earlier render            Subsequent render
   ------------------------------------------------------
1. useState                   useState
2. undefined                  useState
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

So what is going on right here? Let’s dig in.

First off, I will simply let you know the answer:

<div>{pieces.map(Counter)}</div>
<div>{pieces.map(i => <Counter key={i.identity} />)}</div>

Prior to you get started considering it has to do with the key prop, let me simply inform
you it does not. However the important thing prop is essential generally and you’ll be told
about that from my different weblog publish: Working out React’s key
prop

Here is in a different way to make this identical more or less error occur:

serve as Instance() {
  const [count, setCount] = React.useState(0)
  let otherState
  if (rely > 0) {
    React.useEffect(() => {
      console.log('rely', rely)
    })
  }
  const increment = () => setCount(c => c + 1)
  go back <button onClick={increment}>{rely}</button>
}

The purpose is that our Instance part is looking a hook conditionally, this
is going in opposition to the guidelines of hooks and
is the explanation the
eslint-plugin-react-hooks
package deal has a rules-of-hooks rule. You’ll learn extra about this limitation
from the React medical doctors,
however suffice it to mention, you want to make certain that the hooks are all the time referred to as
the similar choice of occasions for a given part.

Good enough, however in our first instance, we don’t seem to be calling hooks conditionally proper? So
why is that this inflicting an issue for us on this case?

Neatly, let’s rewrite our authentic instance relatively:

serve as Counter() {
  const [count, setCount] = React.useState(0)
  const increment = () => setCount(c => c + 1)
  go back <button onClick={increment}>{rely}</button>
}

serve as App() {
  const [items, setItems] = React.useState([])
  const addItem = () => setItems(i => [...i, {id: i.length}])
  go back (
    <div>
      <button onClick={addItem}>Upload Merchandise</button>
      <div>
        {pieces.map(() => {
          go back Counter()
        })}
      </div>
    </div>
  )
}

And you can understand that we are creating a serve as that is simply calling every other
serve as so let’s inline that:

serve as App() {
  const [items, setItems] = React.useState([])
  const addItem = () => setItems(i => [...i, {id: i.length}])
  go back (
    <div>
      <button onClick={addItem}>Upload Merchandise</button>
      <div>
        {pieces.map(() => {
          const [count, setCount] = React.useState(0)
          const increment = () => setCount(c => c + 1)
          go back <button onClick={increment}>{rely}</button>
        })}
      </div>
    </div>
  )
}

Beginning to glance problematic? You can understand that we’ve not in truth modified any
conduct. That is only a refactor. However do you understand the issue now? Let me
repeat what I stated previous: you want to make certain that the hooks are all the time
referred to as the similar choice of occasions for a given part.

In response to our refactor, now we have come to appreciate that the “given part” for all
our useState calls isn’t the App and Counter, however the App by myself. This
is because of the best way we are calling our Counter serve as part. It isn’t a
part in any respect, however a serve as. React does not know the variation between us
calling a serve as in our JSX and inlining it. So it can’t affiliate the rest
to the Counter serve as, as a result of it isn’t being rendered like an element.

This is the reason you want to make use of JSX (or React.createElement)
when rendering elements somewhat than just calling the serve as. That approach, any
hooks which are used will also be registered with the example of the part that
React creates.

So do not name serve as elements. Render them.

Oh, and it is notable to say that now and again it is going to “paintings” to name serve as
elements. Like so:

serve as Counter() {
  const [count, setCount] = React.useState(0)
  const increment = () => setCount(c => c + 1)
  go back <button onClick={increment}>{rely}</button>
}

serve as App() {
  go back (
    <div>
      <div>Here's a counter:</div>
      {Counter()}
    </div>
  )
}

However the hooks which are in Counter might be related to the App part
example, as a result of there is not any Counter part example. So it is going to “paintings,”
however now not the best way you’ll be expecting and it might behave in sudden techniques as you’re making
adjustments. So simply render it in most cases.

Just right success!

You’ll mess around with this in codesandbox:

Edit Don't call function components

[ad_2]

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back To Top
0
Would love your thoughts, please comment.x
()
x