Can I replace context with hooks?

Viewed 2765

Is there a way with new react hooks API to replace a context data fetch?

If you need to load user profile and use it almost everywhere, first you create context and export it:

export const ProfileContext = React.createContext()

Then you import in top component, load data and use provider, like this:

import { ProfileContext } from 'src/shared/ProfileContext'

<ProfileContext.Provider
      value={{ profile: profile, reloadProfile: reloadProfile }}
    >
        <Site />
    </ProfileContext.Provider>

Then in some other components you import profile data like this:

import { ProfileContext } from 'src/shared/ProfileContext'
const context = useContext(profile);

But there is a way to export some function with hooks that will have state and share profile with any component that want to get data?

3 Answers

React provides a useContext hook to make use of Context, which has a signature like

const context = useContext(Context);

useContext accepts a context object (the value returned from React.createContext) and returns the current context value, as given by the nearest context provider for the given context.

When the provider updates, this Hook will trigger a rerender with the latest context value.

You can make use of it in your component like

import { ProfileContext } from 'src/shared/ProfileContext'

const Site = () => {
   const context = useContext(ProfileContext);
   // make use of context values here
}

However if you want to make use of the same context in every component and don't want to import the ProfileContext everywhere you could simply write a custom hook like

import { ProfileContext } from 'src/shared/ProfileContext'
const useProfileContext = () => {
   const context = useContext(ProfileContext);
   return context;
}

and use it in the components like

const Site = () => {
   const context = useProfileContext();
}

However as far a creating a hook which shares data among different component is concerned, Hooks have an instance of the data for them self and don'tshare it unless you make use of Context;

updated:

My previous answer was - You can use custom-hooks with useState for that purpose, but it was wrong because of this fact:

Do two components using the same Hook share state? No. Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.

The right answer how to do it with useContext() provided @ShubhamKhatri

Now i use it like this.

Contexts.js - all context export from one place

export { ClickEventContextProvider,ClickEventContext} from '../contexts/ClickEventContext'
export { PopupContextProvider, PopupContext } from '../contexts/PopupContext'
export { ThemeContextProvider, ThemeContext } from '../contexts/ThemeContext'
export { ProfileContextProvider, ProfileContext } from '../contexts/ProfileContext'
export { WindowSizeContextProvider, WindowSizeContext } from '../contexts/WindowSizeContext'

ClickEventContext.js - one of context examples:

import React, { useState, useEffect } from 'react'

export const ClickEventContext = React.createContext(null)
export const ClickEventContextProvider = props => {
  const [clickEvent, clickEventSet] = useState(false)
  const handleClick = e => clickEventSet(e)

  useEffect(() => {
    window.addEventListener('click', handleClick)
    return () => {
      window.removeEventListener('click', handleClick)
    }
  }, [])

  return (
    <ClickEventContext.Provider value={{ clickEvent }}>
      {props.children}
    </ClickEventContext.Provider>
  )
}

import and use:

import React, { useContext, useEffect } from 'react'
import { ClickEventContext } from 'shared/Contexts'

export function Modal({ show, children }) {
  const { clickEvent } = useContext(ClickEventContext)

  useEffect(() => {
    console.log(clickEvent.target)
  }, [clickEvent])

  return <DivModal show={show}>{children}</DivModal>
}
Related