You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// React.memo prevents re-renders when props haven't changed// Useful for optimizing performance in child componentsconstMemoizedComponent=React.memo(functionMyComponent(props){// Only re-renders if props.value changesreturn<div>{props.value}</div>;});// useMemo caches expensive calculations between renders// Great for heavy computations or complex data transformationsfunctionExpensiveCalculation({ data }){constmemoizedValue=useMemo(()=>{// This calculation only runs when data changesreturndata.reduce((acc,item)=>acc+item,0);},[data]);// Dependency array - controls when to recalculatereturn<div>Result: {memoizedValue}</div>;}// useCallback memoizes functions to maintain reference equality// Important when passing callbacks to optimized child componentsfunctionParentComponent(){const[count,setCount]=useState(0);// This function maintains the same reference between rendersconsthandleClick=useCallback(()=>{setCount(c=>c+1);},[]);// Empty array means function never changesreturn<ChildComponentonClick={handleClick}/>;}
Custom Hooks
// Custom hooks let you extract component logic into reusable functions// This hook tracks window size changesfunctionuseWindowSize(){// Initialize state with current window dimensionsconst[size,setSize]=useState({width: window.innerWidth,height: window.innerHeight});useEffect(()=>{// Handler to call on window resizeconsthandleResize=()=>{setSize({width: window.innerWidth,height: window.innerHeight});};// Subscribe to window resize eventswindow.addEventListener('resize',handleResize);// Cleanup function removes event listenerreturn()=>window.removeEventListener('resize',handleResize);},[]);// Empty array means effect runs once on mountreturnsize;// Return current dimensions}// Custom hook for form handling// Simplifies form state management and input handlingfunctionuseForm(initialState={}){const[values,setValues]=useState(initialState);// Generic change handler for any form inputconsthandleChange=(event)=>{const{ name, value }=event.target;setValues(prev=>({ ...prev,[name]: value}));};// Reset form to initial stateconstresetForm=()=>setValues(initialState);return{ values, handleChange, resetForm };}// Example of using the custom form hookfunctionSignupForm(){// Hook provides form state and handlersconst{ values, handleChange, resetForm }=useForm({username: '',email: '',password: ''});return(<form><inputname="username"value={values.username}onChange={handleChange}/>{/* Other form fields */}</form>);}
Higher-Order Components (HOCs)
// HOCs are functions that take a component and return an enhanced version// This HOC adds loading state handlingfunctionwithLoader(WrappedComponent){returnfunctionWithLoaderComponent({ isLoading, ...props}){// Show loading indicator when isLoading is trueif(isLoading){return<div>Loading...</div>;}// Otherwise, render the wrapped component with its propsreturn<WrappedComponent{...props}/>;};}// HOC for protecting routes that require authenticationfunctionwithAuth(WrappedComponent){returnfunctionWithAuthComponent(props){constisAuthenticated=useAuth();// Custom authentication hook// Redirect to login if not authenticatedif(!isAuthenticated){return<Navigateto="/login"/>;}// Render component if authenticatedreturn<WrappedComponent{...props}/>;};}// Compose multiple HOCs togetherconstProtectedComponent=withAuth(withLoader(UserDashboard));
Render Props
// Render props pattern shares code between components// This component tracks mouse position and shares itclassMouseTrackerextendsReact.Component{state={x: 0,y: 0};// Update state with current mouse positionhandleMouseMove=(event)=>{this.setState({x: event.clientX,y: event.clientY});};render(){// Call the render prop with current statereturn(<divonMouseMove={this.handleMouseMove}>{this.props.render(this.state)}</div>);}}// Example usage showing mouse coordinates<MouseTrackerrender={({ x, y })=>(<div>Mouse position: {x}, {y}</div>)}/>
Code Splitting
// Code splitting helps reduce bundle size// Lazy loading loads components only when neededconstLazyComponent=React.lazy(()=>import('./LazyComponent'));// Suspense provides a loading state while component loadsfunctionApp(){return(<Suspensefallback={<div>Loading...</div>}><LazyComponent/></Suspense>);}// Route-based code splitting// Each route loads its component separatelyconstDashboard=React.lazy(()=>import('./Dashboard'));constSettings=React.lazy(()=>import('./Settings'));functionApp(){return(<Suspensefallback={<div>Loading...</div>}><Routes><Routepath="/dashboard"element={<Dashboard/>}/><Routepath="/settings"element={<Settings/>}/></Routes></Suspense>);}
Advanced Patterns
// Compound Components Pattern// Creates related components that work togetherfunctionMenu({ children }){const[activeIndex,setActiveIndex]=useState(0);// Clone and enhance child elements with additional propsreturnReact.Children.map(children,(child,index)=>{returnReact.cloneElement(child,{isActive: index===activeIndex,onActivate: ()=>setActiveIndex(index)});});}// Subcomponent for Menu itemsMenu.Item=functionMenuItem({ isActive, onActivate, children }){return(<divclassName={isActive ? 'active' : ''}onClick={onActivate}>{children}</div>);};// State Reducer Pattern// Allows customization of state logicfunctionuseCounter({ initialState =0, reducer }){const[count,dispatch]=useReducer(reducer,initialState);constincrement=()=>dispatch({type: 'INCREMENT'});constdecrement=()=>dispatch({type: 'DECREMENT'});return{ count, increment, decrement };}// Example implementation with custom state logicfunctionCounter(){// Custom reducer for counter behaviorconstreducer=(state,action)=>{switch(action.type){case'INCREMENT':
returnstate+1;case'DECREMENT':
returnstate>0 ? state-1 : 0;// Prevent negative valuesdefault:
returnstate;}};const{ count, increment, decrement }=useCounter({initialState: 0,
reducer
});return(<div><buttononClick={decrement}>-</button><span>{count}</span><buttononClick={increment}>+</button></div>);}
Testing
// React Testing Library focuses on testing user interactionsimport{render,fireEvent,screen}from'@testing-library/react';// Basic component rendering testtest('renders counter',()=>{render(<Counter/>);// Check if element exists in documentexpect(screen.getByText('Count: 0')).toBeInTheDocument();});// Testing user interactionstest('increments counter',()=>{render(<Counter/>);// Simulate click eventfireEvent.click(screen.getByText('+'));// Verify counter increasedexpect(screen.getByText('Count: 1')).toBeInTheDocument();});// Testing asynchronous operationstest('loads user data',async()=>{render(<UserProfileuserId="123"/>);// Check loading stateexpect(screen.getByText('Loading...')).toBeInTheDocument();// Wait for data to loadawaitscreen.findByText('User: John');// Verify loaded contentexpect(screen.getByText('User: John')).toBeInTheDocument();});// Testing with mock functionstest('calls onSubmit with form data',()=>{// Create mock functionconsthandleSubmit=jest.fn();render(<FormonSubmit={handleSubmit}/>);// Simulate form inputfireEvent.change(screen.getByLabelText('Username'),{target: {value: 'testuser'}});// Simulate form submissionfireEvent.click(screen.getByText('Submit'));// Verify mock function was called with correct dataexpect(handleSubmit).toHaveBeenCalledWith({username: 'testuser'});});