React 16.8+ supports Hooks.
With Hooks, we can use simple function components to do lots of the fancy
things that we could only do with class components in the past.
React Hooks, plainly put, are functions that let us manage the internal
state of components and handle post-rendering side effects directly
from our function components.
Hooks don’t work inside classes — they let us use fancy React features
without classes.
Keep in mind that function components and React Hooks do not replace class components.
They are completely optional; just a new tool that we can take advantage of.
React offers a number of built-in Hooks.
A few of these include...
useState(), useEffect(), useContext(), useReducer(), and useRef().
The most common hook is probably the useState() hook.
It is a named export from the React library
and is imported like this...
import React, { useState } from 'react'
useState() is a JavaScript function defined in the React library.
When we call this function, it returns an array with two values:-
current state
The current value of this state
state setter
A function that we can use to update the value of this state
Because React returns these two values in an array, we can assign them
to local variables, naming them whatever we like.
For example:
const [toggle, setToggle] = useState();
import React, { useState } from "react"; function Toggle() { const [toggle, setToggle] = useState(); return ( <div> <p>The toggle is {toggle}</p> <button onClick={() => setToggle("On")}>On</button> <button onClick={() => setToggle("Off")}>Off</button> </div> ); }The above code will create a toggle variable (with no value).
import React, {useState } from 'react'; export default function ColorPicker() { const [color, setColor] = useState(); const divStyle = { backgroundColor: color ? color : 'purple' }; return ( <div style={divStyle}> <p> The color is {color ? color : 'Purple (default)'} </p> <button onClick={() => setColor("Aquamarine")}> Aquamarine </button> <button onClick={() => setColor("BlueViolet")}> BlueViolet </button> <button onClick={() => setColor("Chartreuse")}> Chartreuse </button> button onClick={() => setColor("CornflowerBlue")}> CornflowerBlue </button> </div> ); }In the above I am using useState() to create color and setColor.
Sometimes you will need to set a default value for the property created
by useState()
For example, we may want the default colour in the above examples to
be Green. This can be done by...
const [color, setColor] = useState("Green")
Often, the next value of our state is calculated using the current state.
for example...adding 1 to the current value
In this case, it is best practice to update state with a callback function.
If we do not, we risk capturing outdated, or “stale”, state values.
In this example (below) I am creating a property (called: increment)
that is a function to add 1 to itself using the 'callback function' within
the state hook (setCount). Eg...
const [count, setCount] = useState(0); const increment = () => setCount(prevCount => prevCount + 1);The best I can see is...
import React, { useState } from 'react'; export default function QuizNavBar({ questions }) { const [questionIndex, setQuestionIndex] = useState(0); const goBack = () => { setQuestionIndex( prevQuestionIndex => prevQuestionIndex-1 ); } const goToNext = () => { setQuestionIndex( prevQuestionIndex => prevQuestionIndex+1 ); } // determine if on the first question or not const onFirstQuestion = questionIndex === 0; const onLastQuestion = questionIndex === questions.length - 1; return ( <nav> <span>Question #{questionIndex + 1}</span> <div> <button onClick={goBack} disabled={onFirstQuestion}> Go Back </button> <button onClick={goToNext} disabled={onLastQuestion}> Next Question </button> </div> </nav> ); }
questionIndex is given a starting value = 0, by the...
useState(0) command.
goBack is a function that decreases the questionIndex value by 1...
...the setQuestionIndex() does this through the use of the callback function...
...prevQuestionIndex => prevQuestionIndex-1
goToNext() is similar to goBack() but ADDS 1 to the value instead of reducing the value
of questionIndex
onFirstQuestion returns TRUE (if questionIndex is = 0) or FALSE (if it is not equal to 0)
This says that onFirstQuestion = questionIndex === 0
and here the command questionIndex === 0 is not a calculation it is just
more of a question, so if the value of questionIndex is 0 then it
returns TRUE (if not it returns FALSE).
onLastQuestion checks if the value of questionIndex is equal to the number
questions there are and if so return TRUE (otherwise return FALSE).
And in the main return section the button to goBack
fires the onClick event - which is the goBack() function - and then
reduces the count.
The disabled event calls onFirstQuestion() and if it gets
back TRUE it will disable the button.
While the goToNext button adds 1 to the count and disables the button if it is
at the maximum number of questions.
import React, { useState } from "react"; import ItemList from "./ItemList"; import { produce, pantryItems } from "./storeItems"; export default function GroceryCart() { const [cart, setCart] = useState([]); const addItem = (item) => { setCart((prev) => { return [item, ...prev]; }); }; const removeItem = (targetIndex) => { setCart( (prev) => { return ( prev.filter((item, index) => index !== targetIndex); ) } ); }; return ( <div> <h1>Grocery Cart</h1> <ul> {cart.map((item, index) => ( <li onClick={() => removeItem(index)} key={index}> {item} >/li> ))} </ul> <h2>Produce</h2> <ItemList items={produce} onItemClick={addItem} /> <h2>Pantry Items</h2> <ItemList items={pantryItems} onItemClick={addItem} /> </div> ); }
The pane on the left is part of the code for choosing food items from
two different lists (Produce and Pantry items).
Here, though, I just want to expand on two things...
addItem()
removeItem()
When working with variables it can be useful to
group them in an object.
const [profile, setProfile] = useState( {} )
creates a 'state hook'
variable called profile
the {} tells React to create it as an EMPTY OBJECT.
Then when we want to populate the profile object we would normally say something like...
setProfile(
myName: "Gary",
myTest: "Test",
)
which would create profile.myName (the value would be "Gary")
When working with variables it can be useful to
group them in an object.
const [profile, setProfile] = useState( {
title: "Best Musical Ever",
actors: ["George Wilson", "Tim Hughes", "Larry Clements"],
locations: {
Chicago: {
dates: ["1/1", "2/2"]
} )
creates a 'state hook'
variable called profile
this time it populates profile when created
and refer them as profile.title (the value would be "Best Musical Ever")
This example also creates profile.actors as an array.
And profile.locations as an object which holds profile.locations.Chicago.dates and
.dates itself is an array.