This article has been publish in my personal blog
Redux is a library used for managing global state, it can be used with or without React, but in this tutorial, we are going to take a look at how we can use Redux together with React.
You will need the following tools:
- A code editor - I will be using VSCode but you can use any you like.
- npm & npx
- Install on Linux:
sudo apt install npm nodejs ;npm i -g npx
- Install on Windows
- Install on Linux:
Initial setup
First, we are going to start by creating a ReactJS app and installing Redux.
I will be using Typescript but you
can also do it in Javascript:
Run the following commands in the terminal. (If you want to do it in Javascript,
make sure you remove the “—template typescript”
flag)
npx create-react-app my-react-redux-app --template typescript
cd my-react-redux-app
Now we need 2 libraries for redux, the first one has the redux API and the second one has the Redux configured to be used with React.
npm i @reduxjs/toolkit react-redux
Now go ahead and replace the content of App.tsx with the following:
Don’t worry about it as it's just JSX
with an input whose value we are going to save in the store when the button is clicked.
import { useState } from "react";
function App() {
const [localStateName, setLocalStateName] = useState("");
return (
<div className="App">
<input
type="text"
placeholder="name"
value={localStoreName}
onChange={(e) => setLocalStoreName(e.target.value)}
/>
<button>Submit to store</button>
<br /> <br /> <hr />
Name in the store: <code>asd</code>
</div>
);
}
export default App;
Store Setup
Next, we are going to configure the store and create a reducer that will handle our state changes
Redux state is immutable
and the only way to update it is using reducers.
Think of reducers as state machines, they handle how the state is changed.
First, create a new file called store.ts (or store.js if you are not using typescript),
import a function called configureStore, and create an empty store with it:
import { configureStore } from "@reduxjs/toolkit";
export const myStore = configureStore({ reducer: () => {} });
Now go ahead and import createSlice from the same library and create a reducer with it. createSlice is a wrapper around the old API from redux which reduces quite some boilerplate when creating reducers.
createSlice requires an object with 3 arguments. The name of the reducer, the initial
state of the sub-store, and the reducer itself. You can place the code just above
myStore.
export const { actions, reducer } = createSlice({
name: "user",
initialState: { name: "" } as { name: string },
reducers: {},
});
Now we can add our reducer to the store configuration. Modify myStore so it gets the reducer we created:
export const myStore = configureStore({ reducer: reducer });
Actions
We dispatch an action to the reducer when we want to have a state change. And the reducer will know what function to trigger for updating the state based on the action that we dispatch. But first, we need to create actions that we can use. For now, let us create 1 action and call it “nameUpdated”. Basically, it will update the "name"`property we have in the state with whatever payload we give.
Payloads
can be passed when you dispatch an action. We are going to take a look at that a
bit later.
Inside the createSlice in the reducers property, add a function called nameUpdated
like below
`tsx
import {
configureStore,
createSlice,
PayloadAction, // Typescript type used to type the action.
} from "@reduxjs/toolkit";
export const { actions, reducer } = createSlice({
...
reducers: {
nameUpdated: (state, action: PayloadAction) => {
state.name = action.payload;
},
},
});
`
Redux Provider for React
Later we are going to use hooks to work with the redux store from react components. And those hooks need access to the redux store. react-redux allows that by providing a React context provider to us, we can wrap our App with.
You can do so by going to index.ts (or index.js) and importing the initStore you
created earlier and the Provider from “react-redux”
tsx
import { initStore } from "./store";
import { Provider as ReduxProvider } from "react-redux";
Now you can wrap the App with the Provider and pass the initStore through the store prop.
tsx
...
root.render(
<React.StrictMode>
<ReduxProvider store={initStore}>
<App />
</ReduxProvider>
</React.StrictMode>
);
Updating the store
We are going to update the store by dispatching the actions that we created earlier. Let's go in the App.tsx file and do that when the user clicks the submit button. First, import the useDispatch hook from react-redux and import the actions you created from store.ts
tsx
import { useDispatch } from "react-redux";
import { actions } from "./store";
Now let us get the dispatch function from useDispatch hook by executing it and getting its return value.
`tsx
function App() {
const dispatch = useDispatch()
const [localStateName, setLocalStateName] = useState("");
...
}
`
Next, we are going to create the click handler, so when we click the submit button it will dispatch the action and change the state with the value that is in the localStateName. Create the function just below the useState hook and dispatch the nameUpdated action.
`tsx
function App() {
...
const [localStateName, setLocalStateName] = useState("");
const handleClick = () => {
dispatch(actions.nameUpdated(localStateName));
};
...
`
We can just pass this function to the submit button as click handler and when we click in the submit button it is going to change the state.
tsx
function App() {
...
return (
...
<button onClick={handleClick}>Submit to store</button>
...
);
}
I would suggest you install the Redux Devtools and then you can track any changes to the redux state. For example, let's type some random input and press submit to see what changes in the state.
You can open Redux Devtools by opening the chrome dev tools (normally F12) and finding
the redux tab. Should be at the end if you just installed it.
Now type something in the input and press “Submit to store”
We can see that the name in the state has changed to the value we typed in the input.
You can play around with the dev tools a bit to get used to them as they can be really
helpful. Check out this tutorial on how to use the Redux devtools.
Selecting the state
react-redux gives us a hook called useSelector, which we can use to select a state from the store. It accepts a callback where it will pass the state as the first argument and will cause the component to rerender every time the return value of the callback changes.
Go ahead and import it from react-redux like below
tsx
import { useDispatch, useSelector } from "react-redux";
Lets use it to get our name value from the state.
`tsx
const [localStateName, setLocalStateName] = useState("");
const name = useSelector(({ name }: { name: string }) => name);
const handleClick = () => {
...
`
Now you can render the name directly in JSX
tsx
...
Name in the store: <code>{name}</code>
...
Now every time you type something and press submit the state in redux is going to get updated and will inform your component of the update and will change the rendered value for you.
Conclusion
Redux is a very scalable library for managing global states, is being used everywhere, from e-commerce stores to anything that requires state management. And it seems like the perfect match for React. I use it almost every day and can say that I’m very happy with it.
If you liked the tutorial make sure you follow me on Twitter
to get the latest articles, or if you would like a tutorial on something you prefer,
make sure you let me know about it and I’ll do my best to bring it to you. My email
is support@learnfrontend.io
Are you interested in reading more about Frontend in general? Then make sure you follow us on Twitter to get the latest updates.
Top comments (0)