Back
⚛️

React

frontenduihooks

Hooks

HookPurposeExample
useStateLocal stateconst [count, setCount] = useState(0)
useEffectSide effects, subscriptionsuseEffect(() => { fetch() }, [dep])
useRefMutable ref, persists across rendersconst ref = useRef(null)
useMemoMemoize computed valueconst x = useMemo(() => compute(a), [a])
useCallbackMemoize functionconst fn = useCallback(() => {}, [dep])
useReducerComplex state logicconst [state, dispatch] = useReducer(reducer, init)
useContextConsume contextconst value = useContext(MyContext)
// useState - functional update for prev state
setCount(prev => prev + 1);

// useEffect - cleanup
useEffect(() => {
  const sub = subscribe();
  return () => sub.unsubscribe();
}, []);

// useReducer
const reducer = (state, action) => {
  switch (action.type) {
    case 'increment': return { count: state.count + 1 };
    default: return state;
  }
};

Component Patterns

// Composition
<Card>
  <CardHeader title="Hi" />
  <CardBody>{children}</CardBody>
</Card>

// Children
function Layout({ children }) {
  return <div className="layout">{children}</div>;
}

// Render props
<DataFetcher url="/api" render={data => <List items={data} />} />

Event Handling

// Synthetic events, pass handler
<button onClick={handleClick}>Click</button>

// With args - use arrow or bind
<button onClick={() => handleDelete(id)}>Delete</button>

// Prevent default
<form onSubmit={e => { e.preventDefault(); submit(); }}>

Conditional Rendering

// && short-circuit
{isLoggedIn && <Dashboard />}

// Ternary
{loading ? <Spinner /> : <Content />}

// Early return
if (!user) return <Login />;
return <Profile user={user} />;

List Rendering with Keys

// Key must be stable, unique among siblings (not index for dynamic lists)
{items.map(item => (
  <li key={item.id}>{item.name}</li>
))}

// Key on outermost element of map
{items.map(item => (
  <Fragment key={item.id}>
    <dt>{item.term}</dt>
    <dd>{item.def}</dd>
  </Fragment>
))}

Refs and DOM

const inputRef = useRef(null);

// Access DOM
inputRef.current?.focus();

// Forward ref to child
const FancyInput = forwardRef((props, ref) => (
  <input ref={ref} {...props} />
));

Context API

// Create
const ThemeContext = createContext('light');

// Provide
<ThemeContext.Provider value="dark">
  <App />
</ThemeContext.Provider>

// Consume
const theme = useContext(ThemeContext);

Performance

ToolWhen to use
React.memoPrevent re-render when props unchanged
useMemoExpensive computation, referential equality for deps
useCallbackStable fn reference for child props / deps
// memo - shallow prop compare
const MemoChild = memo(({ name }) => <span>{name}</span>);

// useMemo - skip recompute
const sorted = useMemo(() => items.sort(...), [items]);

// useCallback - stable fn for useEffect/child
const handleClick = useCallback(() => doSomething(id), [id]);