Learn React — Light

Essential React Patterns: Lifting State Up, HOC, Context & more

1. Lifting State Up

Idea: When multiple sibling components need the same state, move the state to their nearest common parent and pass it down via props.

Why? Keeps a single source of truth and avoids inconsistent UI.

// Parent holds state and passes value + updater to children
function Parent(){
  const [text, setText] = React.useState('')
  return (
    <>
      <Input label="A" value={text} onChange={setText} />
      <Input label="B" value={text} onChange={setText} />
    </>
  )
}

2. Higher-Order Component (HOC)

Idea: An HOC is a function that takes a component and returns an enhanced component. Use it to reuse cross-cutting logic.

Example use-cases: loading states, feature flags, logging, authentication wrappers.

function withLoading(Component){
  return function(props){
    if(props.isLoading) return <div>Loading...</div>
    return <Component {...props} />
  }
}

3. Render Props

Idea: Instead of passing data only, pass a function (render prop) so the parent controls rendering using provided data.

<DataProvider>
  {data => <Chart data={data} />}
</DataProvider>

4. Context API

Idea: Provide global values (theme, user, locale) to components deep in the tree without prop drilling.

const ThemeContext = React.createContext('light')
// <ThemeContext.Provider value={...}> ... </Provider>
// useContext(ThemeContext) to read

5. Custom Hooks

Idea: Extract reusable, stateful logic into functions starting with use.

function useToggle(initial=false){
  const [on, setOn] = React.useState(initial)
  return [on, () => setOn(v => !v)]
}

6. Controlled vs Uncontrolled Components

Controlled: React state drives the input value.
Uncontrolled: Input keeps its own state — accessed via refs.

// Controlled
<input value={state} onChange={...} />

// Uncontrolled
const ref = useRef(); <input ref={ref} /> // read ref.current.value

7. Portals

Render a subtree into a DOM node outside the parent hierarchy — useful for modals, tooltips.

ReactDOM.createPortal(<Modal />, document.getElementById('portal-root'))

8. Error Boundaries

Error boundaries are React class components that catch render errors in children and show fallback UI.

class ErrorBoundary extends React.Component{
  state={hasError:false}
  static getDerivedStateFromError(){return {hasError:true}}
  render(){ return this.state.hasError ? <div>Something went wrong</div> : this.props.children }
}

9. Code Splitting & Memoization

Load components lazily with React.lazy and avoid re-renders with React.memo, useMemo and useCallback.

const Heavy = React.lazy(() => import('./Heavy'))
const MemoComp = React.memo(function MyComp(props){...})