DEV Community

Rustam Apay
Rustam Apay

Posted on • Edited on

React Typescript Provider Boilerplate Snippet

screenshot of code

Hi friends. In my last projects I use providers a lot:

  • Auth (login, logout, user)
  • AppState (which part of the app is loaded and which is not, user settings)
  • NavigationProvider (page neighbors, go next, go back)
  • ModalsProvider (open in modal form a component with some props)

So I came up with a provider snippet, which is easy to copy, past, expand and use from everywhere.

Boilerplate

Provider.tsx

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

// rename Context and Provider to something meaningful, they will be imported from other components

interface Props {
    children: JSX.Element | JSX.Element[]
}

interface State {}

interface Methods {}

interface ContextType {
    state: State
    methods: Methods
}

const defaultContextValue = {} as ContextType

export const Context = createContext<ContextType>(defaultContextValue)

const defaultState = {}

const Provider: React.FC<Props> = ({ children }) => {
    const [state, setState] = useState<State>(defaultState)

    // here write some functions that change state, then put them to the mothods object 

    const methods = {}

    const contextValue = { state, methods }

    return <Context.Provider value={contextValue}>{children}</Context.Provider>
}

export default Provider
Enter fullscreen mode Exit fullscreen mode

Usage example

Provider

App.tsx

import Provider1 from './Provider1'
import Provider2 from './Provider2'

const App = () => {
    return (
        <Provider1>
            <Provider2>

            </Provider2>
        </Provider1>
    )
}

Enter fullscreen mode Exit fullscreen mode

Context

When every provider has the same structure, you can use any of them easily/intuitively from anywhere.

Component.ts


import { useContext } from 'react'
import { Context1 } from './Provider1'
import { Context2 } from './Provider2'

const Component = () => {
    const { state: provider1State, methods: provider1Methods } =
        useContext(Context1)
    const { state: provider2State, methods: provider2Methods } =
        useContext(Context2)

    return (
        <div className='someComponent'>
            <div>{provider1State.someField}</div>
            <div>{provider2State.someField}</div>
            <button>provider1Methods.someMethod</button>
            <button>provider2Methods.someMethod</button>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

In a real project you'll have meaningful names for every provider (not Provider1, Provider2 as in the example above) so it'll be easy to read and write code even when many providers meats together in one component. E.g. authState.userName, authMethods.login, appState.contentLoaded.

If you don't like such an approach, look at useReducer hook.

Top comments (0)