React Learning and Notes
Paul Brown · 06/04/2024 · 2 min read
useState
-
useState
is a 'hook' ('hooks' are functions in React for 'hooking into' state and lifecycle methods -- though this loosely makes sense to me, I've got no real deep understanding so I'll need to revisit this concept). - It is used for handling state in a component. Like so:
// import the main React library from the react package -- this allows us to use the JSX syntax
import React from "react"
// also import useState; can then be used as React.useState = ...
import React, useState from "react"
// preference is to destructure the import, allowing references to useState = ...
import React, {useState} from "react"
- Calling
useState
returns an array to the user. The array's first element is the default value of the piece of state you pass to it; the array's second element is the function used to set/update the state's value. So:
const [counter, setCounter] = useState(0)
gives us: (1) a variable called counter
which holds the value of a piece of state and (2) a function called setCounter
to which we pass either (i) an updated value for the state or (ii) a callback function, the result of which will be set as the value of the state.
- We can use it thus:
const [counter, setCounter] = useState(0)
console.log(counter)
setCounter(1)
// or
setCounter(previousCounter => previousCounter + 1)
- Most likely this updating of state will occur within the body of a function. For instance, if a user clicks a button and it triggers an
onClick
event, like:
import React, {useState} from "react"
export default function App() {
const [count, setCount] = useState(0)
function decrement() {
setCount(prev => prev - 1)
}
function increment() {
setCount(prev => prev + 1)
}
return (
<div>
<button onClick={decrement}>–</button>
<div>
<h1>{count}</h1>
</div>
<button onClick={increment}>+</button>
</div>
)
}
Setting state from child components
Consider the following example: a contact card (the 'parent' component here) and a favourite button in the form of a star icon (the 'child' component here). The star icon needs to know about the favourite status of the contact and is responsible for registering its change, should the user click the icon to go from isFavourite = true
to isFavourite = false
. The star icon component has no access to the main contact object -- this lives on the contact card parent component. The star icon, when called as a component cannot have an onClick
event listener registered to it, either, since it is not itself rendered as a native DOM element. The solution is to maintain a function on the parent element responsible for toggling the isFavourite
property on the contact object but to call that function from an onClick
event listener from the child. The name of this toggling function is passed to the child as a prop.
This is mapped out in the example below:
import React from "react"
import Star from "./Star"
// parent component
export default function App() {
const [contact, setContact] = React.useState({
firstName: "John",
lastName: "Doe",
phone: "+1 (719) 555-1212",
email: "itsmyrealname@example.com",
isFavorite: true
})
function toggleFavorite() {
setContact(prevContact => ({
...prevContact,
isFavorite: !prevContact.isFavorite
}))
}
return (
<main>
<article className="card">
<img src="./images/user.png"/>
<div>
// prop called handleClick, function called toggleFavourite
<Star isFilled={contact.isFavorite} handleClick={toggleFavorite} />
<h2>
{contact.firstName} {contact.lastName}
</h2>
<p>{contact.phone}</p>
<p>{contact.email}</p>
</div>
</article>
</main>
)
}
// child component
import React from "react"
export default function Star({isFilled, handleClick}) {
const starIcon = isFilled ? "star-filled.png" : "star-empty.png"
return (
<img
src={`../images/${starIcon}`}
onClick={handleClick} // event listener added to call parent's function
/>
)
}
Discussions
Login to Post Comments