DEV Community

gasparericmartin
gasparericmartin

Posted on

Union of the State

"Ask not what you can do for state, but what state can do for you." - A Person

The Desire for Dynamism

The process of learning new things can be both exciting and frustrating at turns, especially in cases where one is familiar with the end product of something they're learning how to build. In the case of building applications, the initial peek behind the veil that learning vanilla JavaScript provides quickly turns from fascination to a desire for more. That "more" comes in the form of a framework like React. In very reductive terms, React makes the process of development significantly less labor intensive by managing many of the menial tasks, all but eliminating the need to manually update the DOM, as well as providing powerful tools to build apps. One of those powerful tools is component state, which is incredibly important when seeking to create dynamic applications.

State

In react, state is data that changes via user interaction. By taking advantage of state in React components, we are able to make the component respond to things the user does without involving a parent component. One of the most notable properties of state that makes this possible is the fact that when state changes, the component containing that state and its children will re-render. However, before getting to the re-render we have to both import and initialize our state variable.

import { useState } from "react";

function Component() {
const [stateVariable, setStateVariable] = useState([])
}
Enter fullscreen mode Exit fullscreen mode

We can see here that when initializing a stateful variable, we declare the variable itself, a setter function for making changes, and finally what the initial value of the variable will be. That initial value can be anything we choose, but in this case it's an empty array because of how this variable will be used.

State & Fetch: A Delicious Pairing

There are multiple ways in which React state's re-render behavior can be leveraged to make dynamic apps, but possibly my favorite use is for storing and then displaying data returned from APIs after successful fetch requests. When making an initial GET request to whatever API(s) our app is accessing, we can update our stateful variable(s) with the data returned.

import { useState } from "react";

function Component() {
const [stateVariable, setStateVariable] = useState([])
}

fetch('http://mysteryAPI.com/people')
     .then((response) => response.json())
     .then((data) => setStateVariable(data)
Enter fullscreen mode Exit fullscreen mode

This in and of itself isn't particularly special. In fact, if this were all we were going to do, we wouldn't need to use state at all. We could simply use a non-stateful variable and render whatever data we've had returned. It's our next step where things get more interesting. When there are changes made to the data we want to display to our user, we want to render those changes as they occur. While those changes could be triggered by non-user sources, here we'll discuss user driven changes. For instance, if we have a form for the user to add another name to our database, when the user submits that form we would want what's displayed to match what's happening on the backend. This is where the pairing of state and fetch is particularly useful. Our user submits the form and a POST request is made to the API:

fetch('http://mysteryAPI.com/people', {
     method: 'POST',
     headers: {
           'content-type': 'application/json'
          }
     body: JSON.stringify(newName)
     }
     .then((response) => response.json())
     .then((data) => setStateVariable([...stateVariable, data])
Enter fullscreen mode Exit fullscreen mode

Upon a successful POST request, the data returned from the API will be whatever was added to the database, in this case the new name input by the user. Using this returned data, we can update our state variable by calling our setter function and passing in an array containing a copy of the current data stored in the variable, and the new data to be added to the array. Once state has changed, the component where the variable lives and all of its children will re-render, displaying all of the names from our database wherever they're being rendered. Please keep in mind that this is a simplified explanation that does not take error handling into account.

Ultimately, this pairing of state and fetch provides a streamlined method of displaying the data we receive from our API in response to user generated requests. Instead of having to manually re-render our components each time a request is made, React does it for us every time we update state. Additionally, the ability to simply pass our stateful variable to child components and have them re-render each time it changes makes for much dryer code.

Temptation

State is a powerful tool, and it can be very tempting to use stateful variables everywhere. However, it's inadvisable to do so as it can potentially overcomplicate our code and lead to bugs. Using state sparingly is best, and while there are many cases where we may initially think that a state variable is the way to go, thinking about it for a bit longer can yield a cleaner solution.

Top comments (0)