Can we define conditional Hooks?

What if we wanted to add a checkbox that toggles the use of the first name field?

Let's find out by implementing such a checkbox:

  1. First, we add a new Hook in order to store the state of our checkbox:
    const [ enableFirstName, setEnableFirstName ] = useState(false)
  1. Then, we define a handler function:
    function handleEnableChange (evt) {
setEnableFirstName(!enableFirstName)
}
  1. Next, we render a checkbox:
            <input type="checkbox" value={enableFirstName} onChange={handleEnableChange} />
  1. We do not want to show the first name if it is disabled. Edit the following existing line in order to add a check for the enableFirstName variable:
            <h1>My name is: {enableFirstName ? name : ''} {lastName}</h1>
  1. Could we put the Hook definition into an if condition, or a ternary expression, like we are in the following code snippet?
    const [ name, setName ] = enableFirstName
? useState('')
: [ '', () => {} ]
  1. The latest version of react-scripts actually throws an error when defining conditional Hooks, so we need to downgrade the library for this example, by running the following command:
> npm install --save react-scripts@^2.1.8

Here, we either use the Hook, or if the first name is disabled, we return the initial state and an empty setter function so that editing the input field will not work.

If we now try out this code, we are going to notice that editing the last name still works, but editing the first name does not work, which is what we wanted. As we can see in the following screenshot, only editing the last name works now:

State of the app before checking the checkbox

When we click the checkbox, something strange happens:

  • The checkbox is checked
  • The first name input field is enabled
  • The value of the last name field is now the value of the first name field

We can see the result of clicking the checkbox in the following screenshot:

State of the app after checking the checkbox

We can see that the last name state is now in the first name field. The values have been swapped because the order of Hooks matters. As we know from our implementation, we use the currentHook index in order to know where the state of each Hook is stored. However, when we insert an additional Hook in-between two existing Hooks, the order gets messed up.

Before checking the checkbox, the values array was as follows:

  • [false, '']
  • Hook order: enableFirstName, lastName

Then, we entered some text in the lastName field:

  • [false, 'Hook']
  • Hook order: enableFirstName, lastName

Next, we toggled the checkbox, which activated our new Hook:

  • [true, 'Hook', '']
  • Hook order: enableFirstName, name, lastName

As we can see, inserting a new Hook in-between two existing Hooks makes the name Hook steal the state from the next Hook (lastName) because it now has the same index that the lastName Hook previously had. Now, the lastName Hook does not have a value, which causes it to set the initial value (an empty string). As a result, toggling the checkbox puts the value of the lastName field into the name field.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.120.109