DEV Community

Cover image for New Redux ๐Ÿ˜ฑ is just ๐Ÿ”ฅ
Rajesh Joshi
Rajesh Joshi

Posted on

New Redux ๐Ÿ˜ฑ is just ๐Ÿ”ฅ

React Redux is the official React binding for Redux. It allows React components to read data from a Redux Store, and dispatch Actions to the Store to update data.

Redux helps apps to scale by providing a sensible way to manage state through a unidirectional data flow model. React Redux is conceptually simple. It subscribes to the Redux store, checks to see if the data which your component wants have changed, and re-renders your component.


Let's Code a simple Counter App ๐Ÿš€

Create new React App

$ npx create-react-app learn-redux
Enter fullscreen mode Exit fullscreen mode

Add Redux and Redux Toolkit

$ yarn add @reduxjs/toolkit react-redux
Enter fullscreen mode Exit fullscreen mode

Redux Toolkit is official, opinionated, batteries-included toolset for efficient Redux development. It includes the most widely used Redux addons, like Redux Thunk for async logic and Reselect for writing selector functions, so that you can use them right away.

Directory Structure

src
โ”‚   App.js
โ”‚   index.js
โ”‚
โ””โ”€โ”€โ”€redux
โ”‚   โ”‚   store.js
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€counter
โ”‚       โ”‚   counterSlice.js
Enter fullscreen mode Exit fullscreen mode

Create a Redux Store

in the file src/redux/store.js

import { configureStore } from "@reduxjs/toolkit";

export default configureStore({
  reducer: {},
});
Enter fullscreen mode Exit fullscreen mode

Provide the Redux Store to React

in the file src/index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import store from "./redux/store";
import { Provider } from "react-redux";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

Create a Redux State Slice for Counter

in the file src/store/counter/counterSlice.js

import { createSlice } from "@reduxjs/toolkit";

export const counterSlice = createSlice({
  name: "counter",
  initialState: {
    value: 0,
  },
  reducers: {
    setCounter: (state, action) => {
      state.value = action.payload;
    },
  },
});

// Action creators are generated for each case reducer function
export const { setCounter } = counterSlice.actions;

export default counterSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

Add Slice Reducers to the Store

in the file src/redux/store.js

import { configureStore } from "@reduxjs/toolkit";
import counter from "./counter/counterSlice";

export default configureStore({
  reducer: {
    counter,
  },
});
Enter fullscreen mode Exit fullscreen mode

Write App.js

export default function App() {
  return (
    <div>
      <button aria-label="Increment value">Increment</button>
      <span>#</span>
      <button aria-label="Decrement value">Decrement</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Import requirements

import { useSelector, useDispatch } from "react-redux";
import { setCounter } from "./redux/counter/counterSlice";
Enter fullscreen mode Exit fullscreen mode
  • useSelector will be used to fetch data from the global store

  • useDispatch will be used to update the data in the global store

Create Counter variable and insialize the dispatch

const counter = useSelector((state) => state.counter);

const dispatch = useDispatch();
Enter fullscreen mode Exit fullscreen mode

Accessing the counter value

Update the span tag accordingly.

<span>#{counter.value}</span>
Enter fullscreen mode Exit fullscreen mode

Writing on Click Events

  • Increment Button
<button
  aria-label="Increment value"
  onClick={() => dispatch(setCounter(counter.value + 1))}
>
  Increment
</button>
Enter fullscreen mode Exit fullscreen mode
  • Decrement Button
<button
  aria-label="Decrement value"
  onClick={() => dispatch(setCounter(counter.value - 1))}
>
  Decrement
</button>
Enter fullscreen mode Exit fullscreen mode

App.js looks like this

import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { setCounter } from "./redux/counter/counterSlice";

export default function App() {
  const counter = useSelector((state) => state.counter);

  const dispatch = useDispatch();

  return (
    <div>
      <button
        aria-label="Increment value"
        onClick={() => dispatch(setCounter(counter.value + 1))}
      >
        Increment
      </button>
      <span>{counter.value}</span>
      <button
        aria-label="Decrement value"
        onClick={() => dispatch(setCounter(counter.value - 1))}
      >
        Decrement
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Run the development Server ๐Ÿš€

$ yarn start
Enter fullscreen mode Exit fullscreen mode

React Redux Demo

And, if you hit and of the counter buttons, you'll see the updated values of the counter in the UI.

React Redux


Hurray! You just learned What's new is React Redux.


I hope, you guys liked this quick tutorial. If so, then please don't forget to drop a Like โค๏ธ

And also, help me reach 1k Subscribers ๐Ÿคฉ, on my YouTube channel.

Happy Coding! ๐Ÿ˜ƒ๐Ÿ’ป

Top comments (8)

Collapse
 
valeriavg profile image
Valeria

I feel that Redux articles at this one in particular aren't showing what Redux should be used for.
For the provided example, as well as almost any React project, React's useReducer would be a much better option:

import React, { useReducer } from "react";

export default function App() {
  const [counter, dispatch] = useReducer(
    (state, action) =>
      action === "+" ? state + 1 : action === "-" ? state - 1 : state,
    0
  );

  return (
    <div>
      <button aria-label="Increment value" onClick={() => dispatch("+")}>
        Increment
      </button>
      <span>{counter}</span>
      <button aria-label="Decrement value" onClick={() => dispatch("-")}>
        Decrement
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

And if you need to pass the state along the app, add a React context to the mix.
So why should one add Redux to the project if React already comes shipped with similar tools?

Collapse
 
iakovosvo profile image
iakovosvo

You definitely don't need redux for a counter app but once your app starts growing and getting more complex you might end up implementing redux yourself.

Collapse
 
ivan_jrmc profile image
Ivan Jeremic • Edited

React is soon getting a useSelector hook in core which makes redux useless.

Thread Thread
 
phryneas profile image
Lenz Weber

That has been in discussion in years. It might happen, but I would not make any bets on how the final Api will look or write code anticipating it today.

Thread Thread
 
ivan_jrmc profile image
Ivan Jeremic

Until then Valtio is the cleanest solution out there no competition.

Collapse
 
valeriavg profile image
Valeria

Not really, in most cases you're better off with scoped states for a complex app. It makes it much easier to test and maintain.

I think you really need Redux when you need a state that is mutated from a lot of places, so that it makes sense to make it global, or if you want to track the global state of the whole app for the time travel.

Collapse
 
suhakim profile image
sadiul hakim

I love toolkit

Collapse
 
ivan_jrmc profile image
Ivan Jeremic • Edited

Valtio > Redux