Skip to main content

Basic Hooks

useState

Usage and Examples (from React Docs)

useEffect

Usage and Examples (from React Docs)

createContext and useContext

Usage and Examples (from React Docs)

  1. Create the context with the createContext function containing the values you want to share between components.
    import { createContext } from 'react'; 
    const MyContext = createContext<MyContextProps>({
    message: '',
    setMessage: () => {},
    });
  2. Provide the context to the required components.
 <MyContext.Provider value={{ message, setMessage }}>
  1. Then, useContext to access the context values.
const { message } = useContext(MyContext);
"createContext
import { createContext, useContext } from 'react';

interface MyContextProps {
message: string;
setMessage: (value: string) => void;
}

const MyContext = createContext<MyContextProps>({
message: '',
setMessage: () => {},
});

const ComponentOne = () => {
const { message } = useContext(MyContext);

return <div>{message}</div>;
};

const ComponentTwo = () => {
const { setMessage } = useContext(MyContext);

const handleClick = () => {
setMessage('Hello from Component Two');
};

return <button onClick={handleClick}>Set Message</button>;
};

const MyApp = () => {
const [message, setMessage] = React.useState('Hello from MyApp');

return (
<MyContext.Provider value={{ message, setMessage }}>
<div>
<ComponentOne />
<ComponentTwo />
</div>
</MyContext.Provider>
);
};

export default MyApp;

useReducer

Usage and Examples (from React Docs)

  • Define the State and Action interfaces to describe the shape of our state and actions.
  • Define the reducer function, which takes the current state and an action and returns the new state based on the action.
  • In the Counter component, useReducer hook to initialize our state with the initialState object and the reducer function.
  • Define handleIncrement and handleDecrement functions that dispatch the corresponding actions to the reducer function.
  • Render the current count and two buttons that call the handleIncrement and handleDecrement functions respectively when clicked.
useReducer
import React, { useReducer } from 'react';

interface State {
count: number;
}

interface Action {
type: 'INCREMENT' | 'DECREMENT';
payload?: number;
}

const initialState: State = {
count: 0,
};

function reducer(state: State, action: Action) {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + (action.payload || 1) };
case 'DECREMENT':
return { ...state, count: state.count - (action.payload || 1) };
default:
return state;
}
}

export const Counter = () => {
const [state, dispatch] = useReducer(reducer, initialState);

const handleIncrement = () => {
dispatch({ type: 'INCREMENT' });
};

const handleDecrement = () => {
dispatch({ type: 'DECREMENT' });
};

return (
<div>
<h2>Count: {state.count}</h2>
<button onClick={handleIncrement}>Increment</button>
<button onClick={handleDecrement}>Decrement</button>
</div>
);
};

combining useReducer and useContext

  • Full solution with CountProvider component that wraps the Counter component and provides the state and dispatch functions to the Counter component.
useReducer and useContext
import React, { createContext, useContext, useReducer } from 'react';

type Action = { type: 'increment' } | { type: 'decrement' };

type State = { count: number };

type Dispatch = (action: Action) => void;

const initialState: State = { count: 0 };

const CountStateContext = createContext<State | undefined>(undefined);
const CountDispatchContext = createContext<Dispatch | undefined>(undefined);

function countReducer(state: State, action: Action): State {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error(`Unhandled action type: ${action.type}`);
}
}

function CountProvider({ children }: { children: React.ReactNode }) {
const [state, dispatch] = useReducer(countReducer, initialState);
return (
<CountStateContext.Provider value={state}>
<CountDispatchContext.Provider value={dispatch}>
{children}
</CountDispatchContext.Provider>
</CountStateContext.Provider>
);
}

function useCountState() {
const context = useContext(CountStateContext);
if (context === undefined) {
throw new Error('useCountState must be used within a CountProvider');
}
return context;
}

function useCountDispatch() {
const context = useContext(CountDispatchContext);
if (context === undefined) {
throw new Error('useCountDispatch must be used within a CountProvider');
}
return context;
}

function Counter() {
const state = useCountState();
const dispatch = useCountDispatch();
return (
<div>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<span>{state.count}</span>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}

function App() {
return (
<CountProvider>
<Counter />
</CountProvider>
);
}

export default App;

Sum

const sumNumbers = numbers.reduce((sum, value) => sum + value, 0)

Average

const averageNumbers = numbers. reduce((avg, value, _, arr) => avg + value / arr.length, 0);

useRef

Usage and Examples (from React Docs)

useMemo

Usage and Examples (from React Docs)

useCallback

  • cache a function definition between re-renders.

Usage and Examples (from React Docs)

useLayoutEffect

  • version of useEffect that fires before the browser repaints the screen.

Usage and Examples (from React Docs)

useDeferredValue

React docs: "You can also apply useDeferredValue as a performance optimization. It is useful when a part of your UI is slow to re-render, "

import { Suspense, useState, useDeferredValue } from 'react';
import SearchResults from './SearchResults.js';

export default function App() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
const isStale = query !== deferredQuery;
return (
<>
<label>
Search albums:
<input value={query} onChange={e => setQuery(e.target.value)} />
</label>
<Suspense fallback={<h2>Loading...</h2>}>
<div style={{
opacity: isStale ? 0.5 : 1,
transition: isStale ? 'opacity 0.2s 0.2s linear' : 'opacity 0s 0s linear'
}}>
<SearchResults query={deferredQuery} />
</div>
</Suspense>
</>
);
}