Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
Basic Redux and UI Integration
3.
Using Redux with React
3.1.
Designing The Component Tree
3.2.
Reading State Store with useSelector
3.3.
Dispatching Actions with useDispatch
3.4.
Passing the Store with Provider
4.
React-Redux Patterns
4.1.
Global State, Component State and Forms
4.2.
Multiple Selectors in a Component
4.3.
Selecting Data in List Items by ID
5.
Frequently Asked Questions
6.
Key takeaways
Last Updated: Mar 27, 2024

Using Redux with UI and React

Author Reet Maggo
0 upvote
Master Python: Predicting weather forecasts
Speaker
Ashwin Goyal
Product Manager @

Introduction

Taking our previous Todo app concept, we will add a UI layer to it and see how we can integrate Redux with a UI. Particularly, we will discuss how Redux and React work together, along with examples and code snippets for a better understanding.

Also See, Dropdown in React JS, Hooks in React JS

Basic Redux and UI Integration

Redux was designed to work efficiently with React since React allows users to describe their UI as a function of their state, and Redux contains this state and is capable of updating it in response to actions.

With any UI layer, using Redux requires some consistent steps:

  1. Creating some Redux store
  2. Subscribing to the updates
  3. In the subscription callback:
    1. Getting the present store state
    2. Extracting the data needed by this specific UI
    3. Updating the UI with that data
  4. Rendering the UI with its initial state, if necessary
  5. Dispatching Redux actions to respond to the UI inputs

 

// creating a store using the `createStore` function
const store = Redux.createStore(counterReducer)

// subscribing to the updates
store.subscribe(render)

// the UI is some text in a single HTML element
const valueEl = document.getElementById('value')

// running the subscription callback:
function render()
{

  //Getting the present store state
  const state = store.getState()

  // Extracting the data needed this specific UI
  const newValue = state.value.toString()

  // Updating the UI with that data
  valueEl.innerHTML = newValue
}

// Rendering the UI with its initial store state
render()

// Dispatching Redux actions to respond to the UI inputs
document.getElementById('increment').addEventListener('click', function ()
{
  store.dispatch({ type: 'counter/incremented' })
})
Get the tech career you deserve, faster!
Connect with our expert counsellors to understand how to hack your way to success
User rating 4.7/5
1:1 doubt support
95% placement record
Akash Pal
Senior Software Engineer
326% Hike After Job Bootcamp
Himanshu Gusain
Programmer Analyst
32 LPA After Job Bootcamp
After Job
Bootcamp

Using Redux with React

Redux is a separate library; therefore, various "binding" libraries help users use Redux with some UI framework. The React-Redux UI bindings library officially is a package separate from the Redux core, which needs to be installed too:

 

npm install react-redux

Designing The Component Tree

Similar to designing the state structure according to the requirements, users can design the overall set of UI components and define how they relate to each other in that application.

Based on requirements for the todo app concept used in previous blogs, we will need at least this set of components:

  • <App>:for rendering everything else in the application, the root component.
    • <Header>: containing the text input for "new todo" and the checkbox for "complete all todos".
    • <TodoList>: after applying filters, the list of all visible todo items.
      • <TodoListItem>: an individual todo item with a toggle checkbox to check or uncheck the todo item’s completed status, along with a colour category selector.
    • <Footer>: To show the number of active todo items and filtering controls based on completed status and colour category.

Reading State Store with useSelector

We will first look at one of the React-Redux hooks- the useSelector hook, which is called in the React function components, will give access to React state values. 

We will create the <TodoList> component to read the todo item list from the store, loop over them, and show an individual <TodoListItem> component for each todo entry.

useSelector accepts a single function, called a selector. Selectors take the entire store state as an argument and then read the state value and return it as a result. 

E.g.: The todo app state stores the array of todos as state.todos. A small selector function to return this array for todos is given below:

 

const selectTodo = state => state.todos

 

For the todos marked as completed:

 

const selectCompletedTodos = state =>
{
  const completedTodos = state.todos.filter(todo =>
  todo.completed)

  return completedTodos.length
}

Dispatching Actions with useDispatch

To dispatch actions from a component to the store outside of React, the solution is to call store.dispatch(action). Since we cannot access the store in a component file, there needs to be a way to access the dispatch function itself inside the components. In React, the React-Redux useDispatch hook provides the store's dispatch method as its result. Calling const dispatch = useDispatch() in components needing to dispatch actions, and then calling dispatch(someAction) will be the solution.

In the <Header> component, suppose the users want to type in some new todo item and dispatch the action {type: 'todos/todoAdded'}, containing that text.. The action will be dispatched when the users press the enter key.

 

src/features/header/Header.js
import React, { useState } from 'react'
import { useDispatch } from 'react-redux'

const Header = () =>
{
  const [text, setText] = useState('')
  const dispatch = useDispatch()

  const handleChange = e => setText(e.target.value)

  const handleKeyDown = e =>
  {
    const trimmedText = e.target.value.trim()
    
    // if user presses the enter key
    if (e.key === 'Enter' && trimmedText)
    {
    
      // dispatching the "todo added"
      dispatch({ type: 'todos/todoAdded', payload: trimmedText })
    
      // clearing the input
      setText('')
    }
  }

  return
  (
    <input
      type="text"
      placeholder="What needs to be done?"
      autoFocus={true}
      value={text}
      onChange={handleChange}
      onKeyDown={handleKeyDown}
    />
  )
}

export default Header

Passing the Store with Provider

A hook being a JS function, can't import a store from store.js all by itself. Users need to tell what store they want to use in their components to React-Redux. This can be done by rendering a <Provider> component around the whole <App> and finally passing the store as a prop to <Provider>. 

Adding it to the main index.js file:src/index.js

 

import React from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import App from './App'
import store from './store'
ReactDOM.render
(

  // Render a `<Provider>` around the entire `<App>`,
  // and pass the Redux store to as a prop
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
)

React-Redux Patterns

Global State, Component State and Forms

The app state doesn’t always have to go to the redux store. Only the global state needed across the app must go in the Redux store. The state required in only one place could be kept in the component state.

Multiple Selectors in a Component

At present, it’s only the <TodoList> component reading the data from the store. If the <Footer> component needs to read data too, it will need the following information:

  • The number of todos.
  • The filter value for the current “status”.
  • List of currently selected “colour” categories.

To read these values, the useSelector could be called within one component multiple times. 

Selecting Data in List Items by ID

The app that we have built so far has some performance issues. Since the <TodoList> is currently reading the entire state and passing individual todos as props, any todo object is updated, new memory references of the object and the state array are made. This in turn, triggers the UseSelector hook, which recursively rerenders components. This becomes a big performance issue in bigger apps, and hence, needs an optimal solution. 

The solution for this is to pass just an array of IDs, such that each <TodoListItem> receives a unique ID. Then, we use a hook from React-Redux called ShallowEqual. The UseSelector hook can take a comparison function as a second argument, ShallowEqual in this case. ShallowEqual checks if the array’s contents have changed or not, and UseSelector only re-renders whenever the comparison function returns true.

 

src/features/todos/TodoList.js
import React from 'react'
import { useSelector, shallowEqual } from 'react-redux'
import TodoListItem from './TodoListItem'

const selectTodoIds = state => state.todos.map(todo => todo.id)

const TodoList = () =>
  {
  const todoIds = useSelector(selectTodoIds, shallowEqual)

  const renderedListItems = todoIds.map(todoId => {
    return <TodoListItem key={todoId} id={todoId} />
  })

  return <ul className="todo-list">{renderedListItems}</ul>
}

Frequently Asked Questions

Q1. What is the useSelector?

Ans. The useSelector hook is a function that takes the present state of the app as an argument and returns the data required from it.

 

Q2. How can we select multiple properties in Redux?

Ans. Multiple useSelector hooks with each hook selecting a single property in the store is one of the options to select multiple properties. Another option would be having one useSelector() hook and one selector that combines several properties from the store into a single object.

 

Q3. What is the difference between Redux and hooks?

Ans. Redux holds the global state and actions to be dispatched, while React Hooks only handle the local component state.

 

Q4. What is the difference between connect and useSelector?

Ans. Both useSelector() and connect() are React-redux hooks that could have the same outcome. However, connect() could be used both with class and function components in React, while hooks can only be used with function components. While it is simpler to use hooks, they also allow fewer performance tweaks as compared to connect.

Key takeaways

In this article, we learned about UI’s integration with Redux and understood how React and Redux work together while focusing mainly on the useSelector.

You can go to Coding Ninjas Studio to try and solve more problems for practice. Share this blog with your friends if you found it helpful! Until then, All the best for your future endeavours, and Keep Coding.

Previous article
Concepts of Redux
Next article
Async Logic and Data Fetching in Redux
Live masterclass