React Hooks and State Management
Overview
In the last blog, I introduced simple React elements and component creation (check it out here! - https://www.garudax.id/pulse/introduction-react-david-wei). In this blog, I want to discuss React hooks. React hooks allow the programmer to add state to a function and allow you to abstract logic from one function to another. The state added can be presentation logic and/or business logic. For presentation logic, the state management will be a UI change that occurs based on user action. For business logic, the state management will be the handling of business objects based on business rules. Let's dive in and look at how to use React hooks! By the end, I will demonstrate all the skills learned in making a simple form.
Installations
There will be no new installations needed for this blog. If you want to follow along, check out my first blog linked in the overview to do the environment setup. The alternative option of following along with https://codesandbox.io also works!
Object destructuring
So before we get started with learning and using useState(), let's learn a bit about object destructuring. This is a javascript feature that allows the programmer to extract properties from objects and set them to variables. Let's take a look at some code snippets.
// This is the code inside App.js to print "Hello + name of your choosing
function App(props){
return(
<div className="Sample">
<h1>
Hello {props.name}!
</h1>
</div>
)
}
// Inside index.js we set the name we want to display
ReactDOM.render(
<div>
<App name="David"/>
<SampleState/>
</div>,
document.getElementById('root')
);"
With the code above, we are obtaining "name" property through props.name. We can apply restructuring, to simplify the code. It looks like this:
// This is the the new app.js code with destructuring applied
function App({name}){
return(
<div className="Sample">
<h1>
Hello {name}!
</h1>
</div>
)
}"
Note that on the function line, the destructuring is done with the syntax { } surrounding the property "name". It is important to do this or React will not render your application. Now we can just pull the data by calling name instead of props.name.
This is also quite useful with arrays, suppose we had an array of users with their names in the array. we can use destructuring to access the names in the array freely with variable names and replace "name" in the print statement.
//Replacing the render code in index.js
// our array of users' names
const [one, two, three ] = ["David", "John", "Jane"];
// using destructured variable names instead of "name"
// assigning one into the app name will print Hello David!
// assigning two into the app name will print Hello John! and so on
ReactDOM.render{
<div>
<App name={two}/>
<SampleState/>
</div>,
document.getElementById('root')
);
So calling one in name will print "David", "two" prints "John". You do not have to give every single item in the array a name. If you know which element of the array you wanted to access, say the middle element of the array you can do the following:
const [, two, ] = ["David", "John", "Jane"];
The name assignment for elements of the array can be left blank, but we still have to use comma separations. This would set the name of two to John and the other two names are unset. This would be useful to display a login message or any sort of user message!
useState()
In the last blog, I briefly touched on this hook in the video. A refresher, this React hook helps us add React state to function components. So putting useState together with object destructuring, let's make a user log-in message!
Welcome message example
// dont forget to import use state from the React library
import React, { useState } from "react";
const [one, two, three ] = ["David", "John", "Jane"]
function ShowLoggedInUser(){
const [user, setUser] = useState("No ones logged in");
return (
<div>
// user welcome message, names pulled from the array above
<h1>Welcome: {user}!</h1>
<button onClick ={() => setUser(one)}>Login</button>
</div>
)
};
When working with useState(), it actually returns two items in an array. The item in the first position is the state variable and the item in the second position is the function we use to change the state. That is why we defined our useState() the way we did, "user" is our variable name, and "setUser" is our function used to change the state based on a click action. The value we are setting we are pulling through an array of destructured user names, so either "one", "two", or "three".
Radio button example
Another useful way is to use this in forms, I want to show an example with radio buttons:
function RadioButtonExample(){
const [radio, setRadio] = useState("user 1");
return (
<div>
<h1>Selected Radio button is: {radio}</h1>
<label>User 1:</label>
<input
type="radio"
checked={radio === "user 1"}
value="user 1"
onChange ={(e) => setRadio(e.target.value)}
/>
<br />
<label>User 2:</label>
<input
type="radio"
checked={radio === "user 2"}
value="user 2"
onChange ={(e) => setRadio(e.target.value)}
/>
</div>
);
}
Here we use useState() to dynamically change the state of our message based on the selected radio button. If user 1 is selected, the message will be "Radio button is: user 1". If user 2 is selected, the message will be "Radio button is: user 2". We set the initial state as user 1 and if we click off into user 2, the state of the message dynamically changes to user 2. Pretty cool right?
Something new here is the onChange call. Let's take a look at the onChange in radio button one. "onChange ={(e) => setRadio(e.target.value)}", here the function is if radio button one is clicked we are passing "user 1" as the value with as an event represented by "e" into our useState function and displaying the value in our header message.
useEffect()
Next, let's take a look at useEffect(). This hook can allow you to perform side effects within components. This can be a console.log or an Interaction with a DOM API. This hook can be very useful, let's take a look at some code!
// dont forget to import useEffect
import React, { useEffect } from "react";
useEffect(() => {
document.title = `INTP Blog 2`;
});
If we add this useEffect() into the RadioButtonExample function posted above, we can see that it changes the tab title from "React App" to "INTP Blog 2". Something to watch out for, effects run after every complete render. We may not want this to happen as it takes resources to run. We can control it to only run when certain values are changed.
// Use the initial state as "INTP"
const [courseName, setCourseName] = useState("INTP");
useEffect(() => {
document.title = `${courseName} Blog 2`;
console.log(`${courseName} Blog 2`);
});
If we change the code to the snippet above and open the dev tools in the browser you can see that every time the radio button is clicked and the page renders, useEffect() runs and prints "INTP Blog 2" to the console. To prevent this we simply tell if to only run when courseName updates with the following code.
useEffect(() => {
document.title = `${courseName} Blog 2`;
console.log(`${courseName} Blog 2`);
}, [courseName]);
Now if you check the dev tools again and switch radio button selection the useEffect no longer runs after its initial load. Now it will only run when courseName is changed with setCourseName in the useState().
useRef()
useRef() can be incredibly useful in forms. It can grab the value of a component. For example, it can grab an input component's value. Once the data is captured, we can pass these off to the database or an external process on form submission. Let's see how we can use this to our advantage!
// import for useRef()
import React, { useRef } from "react";
function SampleForm() {
const name = useRef();
const email = useRef();
const submit = (e) => {
// prevents the page from reloading
e.preventDefault();
const nameVal = name.current.value;
const emailVal = email.current.value;
alert(`Name submitted:${nameVal} Email submitted:${emailVal} `);
};
return (
<div>
<form onSubmit={submit}>
<h2>Sample Form</h2>
<label>Name:</label>
// ref is assigned for name input
<input className="exInput" type="text" ref={name}></input>
<br />
<label>Email:</label>
// ref is assigned for email input
<input className="exInput" type="text" ref={email}></input>
<br />
<button type="submit">Submit</button>
</form>
</div>
);
}
The code above is a demonstration of how useRef() grabs input values. After importing in useRef() from the React library, we have to make variables matching the inputs we want to grab values from. This is const name and const email, and we assign the ref value inside of the inputs. ref={name} into name input, ref={email} into email input so useRef() can capture the inputted values.
Then a submit function was made to demonstrate the grabbed values by alerting them through the browser. This is showing the data is grabbed correctly and can be sent off to a database.
Custom Hooks
If we are rewriting the same code in our React project a lot, this is where custom hooks can come into play. We can code our own hooks in a separate Javascript file and import them to use it. So in the case of a form instead of writing the same controlled inputs repeatedly, we can make a custom hook to make the coding process smoother.
import React, { useState } from "react"
export function useInput(initialValue) {
const [value, setValue] = useState(initialValue);
return [
{
value,
onChange: (e) => setValue(e.target.value),
},
//resetting field values
() => setValue(initialValue),
];
};
This custom hook takes in an initial value of the input in the form. Then it handles the state change of the input with the onChange function. After the array of those values is returned, we reset the input after form submission. This hook can be imported anywhere in our project structure and re-used! This custom hook uses useState() specifically but you can use UseEffect() and other libraries to help you write your own custom hook as well. I will give an example of using this in my video demo as well.
Conclusion
Thank you for reading my blogs, I hope you enjoyed them and learned something from them. We now have enough information with blog 1 - introduction to react and blog 2 - react hooks and state management, to make any simple react application! I will go over these skills in detail in my video demo with some form applications. Please check out my sources linked below, they were a huge help in my learning. If you are interested in React I hope you continue learning it! I will be learning alongside you. My blogging journey for React comes to an end, for now, Look forward to potential future blogs!
Code Demo video
Citations
Porcello, E. (2020, December 8). Creating controlled components with usestate - react.js video tutorial: Linkedin learning, formerly Lynda.com. LinkedIn. Retrieved April 6, 2022, from https://www.garudax.id/learning/react-hooks/creating-controlled-components-with-usestate?autoSkip=true&autoplay=true&resume=false&u=2245281
Tekumalla, S. (2019, May 23). Choosing the Right State Management Solution - React.js video tutorial: Linkedin learning, formerly Lynda.com. LinkedIn. Retrieved April 6, 2022, from https://www.garudax.id/learning/react-state-management/choosing-the-right-state-management-solution?autoplay=true&resume=false&u=2245281
React – a JavaScript library for building user interfaces. – A JavaScript library for building user interfaces. (n.d.). Retrieved April 6, 2022, from https://reactjs.org/