Shamaayil Ahmed

Shamaayil Ahmed

React Hook #4 useReducer()

React Hook #4 useReducer()

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

React Hooks are v16.8 specification which allows certain backward compactible functionalities without any use of class based ordering.

Let's see the better version of useState for complex state logic and better state management. And optimal for optimizing performance in components.

Let me get this straight

The need for good developers is to get an optimized and well performing sites up and running. In context of react components the states may increase at a proportionate rate as of the application which even decreases the performance of the same.

For avoiding this scenario React core team came up with Reducers hook.

Reducer is a function which got some changes that's to be reflected in the application. Which takes in actions to actually determine those changes.

useReducer

Whenever you hear this makeup your mind to take up four arguments

  • state: object to store all the states in whole application components
  • dispatch: function to call certain action at the moment some change occurs, has a payload object for new data
  • reducer: function that holds logic for changes to be done
  • initial state: object to pass the initial values of all the state

Don't wanna boredom you with some definition let's get back to the core.

index.js

import React, { useState, useReducer } from 'react';
import Modal from './Modal';           //custom component
import { data } from '../../../data';     //some static data
import { reducer } from './reducer'   // reducer function

const defaultState = {
  people: [],
  isModalOpen: false,
  modalContent: 'Hello World'
}

const Index = () => {
  const [name, setName] = useState('');
  const [state, dispatch] = useReducer(reducer, defaultState);    //everything mentioned above

  const handleSubmit = (e) => {
    e.preventDefault();
    if (name) {
      // setShowModal(true);      //without useReducer
      // setPeople([...people, { id: new Date().getTime().toString(), name }]);
      // setName('')
      const newItem = { id: new Date().getTime().toString(), name }
      dispatch({ type: 'ADD_ITEM', payload: newItem });
      setName('')
    } else {
      // setShowModal(true);
      dispatch({ type: 'NO_VALUE' });
    }
  }

  const closeModal = () => {
    dispatch({ type: 'CLOSE_MODAL' });
  }

  return <>
    {state.isModalOpen && <Modal modalContent={state.modalContent} closeModal={closeModal} />}
    <form onSubmit={handleSubmit} className='form'>
      <div>
        <input type="text" value={name} onChange={(e) => setName(e.target.value)} />
      </div>
      <button type='submit'>add</button>
    </form>
    {state.people.map((person) => {
      return <div key={person.id} className='item'>
        <h4>{person.name}</h4>
        <button onClick={() => dispatch({ type: 'REMOVE_ITEM', payload: person.id })}>remove</button>
      </div>
    })}
  </>;
};

export default Index;

reducer.js

export const reducer = (state, action) => {
  if (action.type === 'ADD_ITEM') {
    const newPeople = [...state.people, action.payload]
    return { ...state, people: newPeople, isModalOpen: true, modalContent: 'item added' }
  }
  if (action.type === 'NO_VALUE') {
    return { ...state, isModalOpen: true, modalContent: 'add a valid item' }
  }
  if (action.type === 'CLOSE_MODAL') {
    return { ...state, isModalOpen: false }
  }
  if (action.type === 'REMOVE_ITEM') {
    const newPeople = state.people.filter((person) =>
      person.id !== action.payload
    );
    return { ...state, people: newPeople, isModalOpen: true, modalContent: 'item removed' }
  }
  throw new Error('no matching action type');
}

Modal.js

import React, { useEffect } from 'react';

const Modal = ({ modalContent, closeModal }) => {  //takes two props and changes along with state value
  useEffect(() => {
    setTimeout(() => {
      closeModal()
    }, 3000)
  });
  return <div className='modal'>
    <p>{modalContent}</p>
  </div>;
};

export default Modal;

Here we have setup a useReducer hook to take up state, dispatch, reducer and defaultState. Provided a form with a input to add names to people (array) and to display them with a small note with (person added or person removed) for certain actions.

So whenever a name is added or removed we call the dispatch method with a definite type which invokes the reducer function, in turn changing the whole state that was defined earlier.


Major Takeaway

useReducer hook is a better version of useState for complex applications which got a reducer function which does everything.

Let's connect 🔗

Catch me here 👇


Hope you all liked the post, share your impressions and queries below 🙌

 
Share this