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){...})