ReduxJS Intro
In react we have a native tool to manage global states (I’ve spoken about that tool here React-Context), but also we have multiple third party libraries that can help us with this task. One of them is Redux.
Just like Context, Redux is a JS library that helps you manage global states throughout your app.
Redux can be used in any Javascript project, but in this case we will focus on using it with ReactJS (They are commonly used together).
Even though we can use both React Context and Redux in the same project, there are some differences between them:
- One of them is the way they handle states, whereas Context manages them as a component level, Redux uses a central store for all states.
- In general, Context is used in small applications (or parts of a big one) and Redux on big and more complex ones.
- Redux is better when we need to frequently update the stored states.
- The setup for Context is much simpler than the Redux one.
- The states in redux can only be read, and the way to change them is by dispatching an action, which are pure functions (with the same input you will get the same output), which make it more predictable.
How Redux works:
We have the data (states) in the Store, the components subscribe to the store to get the information (all of it or a part of it) and use it, also they can change the data stored, but they do not change it directly, they Dispatch an Action (a javascript object with the operation that the reducer should perform and the new data), this actions are forwarded to the Reducers Functions (this functions are responsible for mutating the Store Data). After the store is updated with the latest data, the subscribed components are notified so that they can use the latest data.
Let’s take the same movie streaming platform example used in the Context post but this time use Redux instead. The structure is the following:
For this example we will also use React Redux (which is a React UI bindings layer for Redux).
- Step 1: Redux is a third party library, so we need to Install it, we can also install react-redux to make it simpler to work with react projects.
- Step 2: On a new file, create the store:
import { createStore } from 'redux';
const initialUserState = { isLoggedIn: false };
const userReducer = (state = initialUserState, action) => {
if (action.type === 'login') {
return {
isLoggedIn: true,
}
}
return state;
};
const store = createStore(userReducer);
export default store;
- Step 3: Provide the Store to the React App, go to the top of the components tree (or as high as you need) and wrap the parent component into the Provider
import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import App from "./App";
import store from "./store/index";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
Now, all the child components of (in this case) <App /> may have access to the store.
- Step 4: Use the store in the components:
In the Login component we want to change the value of isLoggedIn once the user logs into the site
import { useDispatch } from "react-redux";
const Login = () => {
const dispatch = useDispatch();
const onSubmit = (userInfo) => {
`validates the user info`
`if succeeded`
dispatch({ type: 'login' });
}
return (
<Login>
Here it would go the login form
</Login>
);
};
export default Login;
Use dispatch is a hook that dispatches the action to the store, we dispatch an object with a type key of login which will match the condition in the store and change the isLoggedIn flag to true.
With the isLoggedIn value updated, in the MoviesCatalog component we can access it for conditionally render either the movies or something else we want to show to anonymous users.
import { useSelector } from "react-redux";
const MoviesCatalog = () => {
const isLoggedIn = useSelector(state => state.isLoggedIn);
return (
<div>
{isLoggedIn ?
<Catalog /> :
<p>
You have to log in to see the movies
</p>
}
</div>
);
};
export default MoviesCatalog;
With the useSelector hook we can select the part of the state (or all of it) to use in the component. In this example we are retrieving the isLoggedIn flag.