Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sharing states between two components with useReducer

Tags:

reactjs

trying to share the states from one component to another: The state can be accessed from main component but it comes undefined when accessing from a new component This is my reducer:

export const  tableReducer=(state = [], action)=> {
    switch (action.type) {
        case 'SELECTED_LIST':
            state = JSON.parse(JSON.stringify(action.payload));
            return state;
        default:
            return state
    }
}

access it from a different file:

const [userList, usersDispatch] = useReducer(tableReducer, []);

useEffect(() => {
            const list = Object.keys(selectedRowIds).length > 0 ? selectedFlatRows.map(
                    d => d.original.email
                )
             : '';
            usersDispatch({ type: 'SELECTED_LIST', payload: list, });
    
        }, [selectedRowIds, selectedFlatRows]);

and in a new component:

const [userList] = useReducer(tableReducer);

    const deleteUsers = () => {
        console.log(userList)
    }

but here console.log(userList) it results to undefined

like image 378
BizMAN Avatar asked Sep 01 '20 11:09

BizMAN


1 Answers

For Sharing of state between components, you can use Context API with useReducer.

Context API provides a neat way of providing state to child components without ending up with a prop drilling situation. It requires that a Provider is setup, which provides its values to any of its Consumers. Any component that is a child of the Provider can consume the context.

First a piece of context is created.

CustomContext.js

import React from 'react';

const CustomContext = React.createContext();

export function useCustomContext() {
  return React.useContext(CustomContext);
}

export default CustomContext;

We can define your reducer in a seperate file.

TableReducer.js

export const  tableReducer=(state = [], action)=> {
    switch (action.type) {
        case 'SELECTED_LIST':
            state = JSON.parse(JSON.stringify(action.payload));
            return state;
        default:
            return state
    }
}

next is to implement the provider, and give it a value within a "Parent" component (A higher up component)

Parent.js

import CustomContext from './CustomContext'
import { tableReducer } from './TableReducer'

const ParentComponent = () => {

  const [userState, usersDispatch ] = React.useReducer(tableReducer, []);

  const providerState = {
    userState,
    usersDispatch
  }

  return (
    <CustomContext.Provider value={providerState} >
      <ChildComponent /> //Any component within here can access value by using useCustomContext();
    </CustomContext.Provider>
  )
}

now any component nested within <CustomContext.Provider></CustomContext.Provider> can access whatever is passed into "value" prop of the Provider which is your context state and the dispatch method.

The child component will look like this (I have ommited your state values and such..)

Child.js

import { useCustomContext }from './CustomContext'

const ChildComponent = (props) => {

    //your custom state variables and other methods


    const { userState, usersDispatch } = useCustomContext();

    useEffect(() => {
        const list = Object.keys(selectedRowIds).length > 0 ? selectedFlatRows.map(
                d => d.original.email
            )
         : '';
        usersDispatch({ type: 'SELECTED_LIST', payload: list, });

    }, [selectedRowIds, selectedFlatRows]);

  return(
      <div>your components dependent on selectedRowIds, selectedFlatRows<div>
   )

}
like image 93
Gandzal Avatar answered Oct 21 '22 13:10

Gandzal