Skip to content

Instantly share code, notes, and snippets.

@thibaut-d
Last active September 16, 2020 14:03
Show Gist options
  • Save thibaut-d/3c9e4869e8e959b5657db895011938b0 to your computer and use it in GitHub Desktop.
Save thibaut-d/3c9e4869e8e959b5657db895011938b0 to your computer and use it in GitHub Desktop.
Shared state management with React Native and the Context API
import React, { FC } from "react";
import MyComponent from "./MyComponent";
import AnotherComponent from "./AnotherComponent";
import { ContextProvider } from "./ContextProvider";
const App: FC = () => {
return (
<ContextProvider>
<MyComponent />
<AnotherComponent />
</ContextProvider>
);
}
export default App
import React, { createContext, FC } from 'react'
import useCustomHook, { UseCustomHookType, initialCustomHookContext } from './useCustomHook'
// Props type
interface Props {
/** Children components place, shall not be needed here with FC type, yet eslint requires it... */
children: React.ReactNode
}
// Create the context objects
export const CustomHookContext = createContext<UseCustomHookType>(initialCustomHookContext)
/**
* Context provider for user data from firebase
*
* @param props - React
* @returns a context provider for user data
*/
const ContextProvider: FC<Props> = ({ children }: Props) => {
// Get state from custom hook
const customHookReturns = useCustomHook()
// Allow this component to encapsulate a part of the app with the provider
// Such component could encapsulate several providers in a row
return (
<CustomHookContext.Provider value={customHookReturns}>
{/* children transmit the providers to the rest of the app if the user is connected*/}
{children}
</CustomHookContext.Provider>
)
}
import React, { useContext, FC } from "react";
import { StoreContext } from "./StoreProvider";
const MyComponent: FC = () => {
const {input, setInput, output} = useContext(CustomHookContext);
// some awsome logic here
return <View>{output}</View>;
}
export default MyComponent
import { Dispatch, SetStateAction, useEffect, useState } from 'react'
export interface UseCustomHookType {
/** documentation */
input: string | null
/** documentation */
setInput: Dispatch<SetStateAction<string | null>>
/** documentation */
output: string | null
}
// This is used to initialize the context
export const initialCustomHookContext = {
input: null,
setInput: () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return (prevState: string | null): null => null
},
output: null,
} as UseCustomHookType
/**
* Custom hook description
*
* @returns - {@link UseCustomHookType}
*/
const useCustomHook = (): UseCustomHookType => {
const [input, setInput] = useState<string | null>(null)
const [output, setOutput] = useState<string | null>(null)
// calculate new output when input change
useEffect(() => {
let mounted = true
// Declaration
const inputToOutput = async (): Promise<void> => {
// incredible logic
const newOutput = await magicTrick(input)
// don't do that if the component un-mounted during the magic trick
if (mounted) setOutput(newOutput)
}
// launch
inputToOutput()
// Cleanup after un-mount
return (): void => {
mounted = false
}
}, [input])
return {
input,
setInput,
output,
}
}
export default useCustomHook
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment