useState()
and how to use itA hook in a React component is a call to a special function.
All hooks functions begin with the word "use"
There are many hooks, some can be used to provide a function component with stateful elements (like useState
), others can be used to managed side effects (like useEffect
) or to cache/memoize functions and objects (like useCallback
)
In this course, we mostly focus on those two useState
and useEffect
In function component, state is a variable that stores the value belonging to a component that could change over a period of time. And when the state change, the component that contain the state re-render
useState
useState is a Hook that lets you add React state to function components.
const [state, setState] = useState(initialValue);
useState
return?useState
as an argument?useState()
Hook is the initial state which is called initialValue
initialValue
? Each piece of state holds a single value, which can be a number, a string, object, an array, a Boolean, or any other type.initialValue
will only be assigned on the initial render. In later renders, the argument of useState()
will be ignored and the current value will be the one retrieved.setState()
: we can't expect to call setState()
on one line and assume the state has been updated on the next line. The reason is that setState()
is a mere request to update state rather than an immediate command to update it.We now want to build an small React application to see how useState work.
mkdir week-5
cd week-5
mkdir tuesday
cd tuesday
mkdir usestate-demo
cd usestate-demo
npx create-react-app .
import "./App.css";
function App() {
let count = 0;
return (
<div className="App">
<h1>Demo useState</h1>
<div>{count}</div>
</div>
);
}
export default App;
onClick
, give it a function that alert an hello message to the user. Fire the event with a click to see if onClick
work wellconst handleAdd = ()=>{
alert("Hello Jaguar")
}
...
<div>{count}</div>
<button onClick={handleAdd}>+</button>
useState
hook comes into play.Adding state to the component:import {useState} from "react"
...
const [count, setCount] = useState(0);
<div>{count}</div>
setCount
function within the onClick
event and pass the current count
value incremented by 1 to the state count
const handleAdd = () => {
setCount(count + 1);
};
We are now so far working with the our main component: App. Let's split the code into smaller components: the Button
component and the Result
component:
Button
component represent a button elementResult
component display the count's value.Create a folder components inside src folder
Inside components, create two new js file: Button.js and Result.jsI
In Button.js
const Result = () => {
let count = 0;
return <div>{count}</div>;
};
export default Result;
In Result.js
const Button = () => {
return <button>+</button>;
};
export default Button;
rafce
to get the sample template of a function component (hint to remember: you should know what is rafce
stand for)Import those two component into the top-level component of them: App.js
In App.js:
import Button from "./components/Button";
import Result from "./components/Result";
...
return (
<div className="App">
<h1>Demo useState</h1>
<Result />
<Button />
</div>
);
Now, we want our new app work exactly the same with the old on. How can we manage the state
of these components?
Button
and Result
components need access to the count
state element. The Result
component will display it and the Button
component will update it.
When a component needs to access a state element that's owned by its sibling component, one solution is to "lift" that state element one level up and define it inside their parent component. For this case the parent is the App
component.
First, look carefully the code below to understand more about lifting state and make your own version follow the step that I just demo, then try to implement to the Exercise.
//App.js
function App() {
const [count, setCount] = useState(0);
const handleAdd = () => {
setCount(count + 1);
};
return (
<div className="App">
<h1>Demo useState</h1>
<Result count={count} />
<Button handleAdd={handleAdd} />
</div>
);
}
//Result.js
import { useState } from "react";
const Result = ({ count }) => {
return (
<>
<div>{count}</div>
</>
);
};
export default Result;
//Button.js
import { useState } from "react";
const Button = ({ handleAdd }) => {
return <button onClick={handleAdd}>+</button>;
};
export default Button;
Components are all about reusability. Let's make the Button component reusable by changing it so that it can increment the global count with any value, not just 1.
Exercise 3: rewrite the Button
component that can be use for both:
Demo:
This form has the default HTML form behavior of browsing to a new page when the user submits the form.
<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
If you want this behavior in React, it just works. But in most cases, it's convenient to have a JavaScript function that handles the submission of the form and has access to the data that the user entered into the form.
The standard way to achieve this is with a technique called controlled components.
We can combine the two state by making the React state be the "single source of truth". Then the React component that renders a form also controls what happens in that form on subsequent user input.
An input form element whose value is controlled by React in this way is called a "controlled component".
Follow the instruction to create a form with React.
//LoginForm
<form>
<label for="email">Email:</label>
<input type="text" id="email" />
<br />
<label for="password">Password:</label>
<input type="password" id="password" />
<br />
<button type="submit" value="Submit">
Submit
</button>
</form>
const handleSubmit = (event) => {
event.preventDefault();
}
...
<form onSubmit={handleSubmit}>
const [email, setEmail] = useState("");
...
const handleEmail = (event) => {
setEmail(event.target.value);
};
...
<input type="text" id="email" onChange={handleEmail} value={email} />
{email: "yourname@gmail.com", password:123}
Create a form to take those information:
useState
10 times and create 10 handle function?Create a form with the following type of input:
select
)textarea
)localStorage
)