chris bailey

Storing and Retrieving Application State in React

In most modern web applications, the user interface must be stateful. Different users will see other things based on being logged in or not; additional information will be fetched based on target users’ needs, and so on. The state is not fixed. It can and will change throughout user interaction; an example would be moving pieces on a game board.

The state tracks a few things; on the UI end, something like the navigation bar being opened or closed is stored in state, and on the data end, the information we’re fetching, showing, editing, etc., is stored in the state on a per-user basis. React handles this differently than we used to with tools like JQuery; instead of working directly on the DOM in React, we have a virtual DOM, which is a copy of the actual DOM that is edited and then transferred to the user once the work is finished.

🌱 Initializing state

In React state is an instance attribute on a component. State is stored in an object, always accessible by key-value pairs. State needs an initial value that is always set when a component is created. State is not mandatory in a component, but a constructor must exist when it is needed/wanted. Constructors take one argument props and need to register your class as a React component with super(props). Next, we can set a default state by adding key-value pairs to this.state. A basic example will look something like this:

class App extends Component {
	constructor(props) {
		super(props);
		this.state = {
			count: 0
		};
	}
	render() {
		return <div>The count is: {this.state.count}</div>;
	}
}

Access to the state values is obtained through this.state within the class we set our constructor up in.

🔧 Changing state values

Looking at it from the outside, the easiest way to change the state would be to reassign the value like so this.state.count = 1. This is incorrect, and manipulating the state directly should never be done.

React provides us with setState() for altering state values. It’s an asynchronous operation that patches our state and only changes the keys told to change, and everything else will state as is. You can pass in an object directly or a function into setState(). It’s best to think of this operation as a request rather than an immediate command. React behind the scenes may delay the setState call so it can update several components simultaneously to keep app performance at a maximum.

Any state change in React will trigger a re-render of the affected components. This keeps the app constantly up to date with the most recent information provided to it.

Let us take a quick look at a basic example of updating the counter with the onClick event listener:

class App extends Component {
	constructor(props) {
		super(props);
		this.addOne = this.addOne.bind(this);
		this.state = {
			count: 0
		};
	}

	addOne(e) {
		this.setState({ count: this.state.count + 1 });
	}
	render() {
		return (
			<div>
				The count is: {this.state.count}
				<button onClick={this.addOne}>Add one</button>
			</div>
		);
	}
}

🎣 State with hooks

As of React 16.8, we have hooks! This gives us access to state management inside functional components, helping eliminate some of the performance hits from using class-based components. This is just a quick note on setting and editing state inside functional components; I will write a longer post on hooks once I make it to that point in my learning path.

Setting state and the ability to alter it within functional components is now a relatively straightforward process. We’ll use the new API method, useState(), within our component. Let us look at our counter-example done with hooks and walk through the differences.

import React, { useState } from 'React';

const App = () => {
	const [count, setCount] = useState(0);

	const addOne = () => {
		return setCount(count + 1);
	};

	return (
		<div>
			The count is: {count}
			<button onClick={addOne}>add one</button>
		</div>
	);
};

export default App;

We first define our functional component App. We then create our default state for ‘count’ by using the useState() call and passing our default value for count ‘0’ into it. It returns two items; our count and the setCount() function that allows us to alter the associated state. We next create our addOne function that will call setCount and pass the current count + 1. React will then update our state and re-render the components needed.

💥 The end

This was a fundamental overview of state in React. Following posts will go into more in-depth concepts and tools like global state with redux and hooks.