Importanat Interview questions
- Event Loop In Depth
- UseCallBack
- UseMemo
- React.memo
- useRef
Event Loop
Javascript is an asynchronous , single threaded & non-blocking language.
It is non-blocking
due to the Event Loop.
JS can off-loads tasks like async task to other workers and continue executing without waiting for the result.
Event loop helps by managing this task.
Web-Workers are scripts that run in a separate thread from the main JavaScript thread.
A Thread is a smallest unit of execution in a program.Memory is shared b/w threads.
Think like this. A Process is a Restaurant(application)
and Threads are like chefs
working on different task but sharing same kitchen(memory).
Jargons
- Call Stack : This is where our code is executed.
- Web APIs : When async op. like
setTimeout fetch
are called, they are handled by Web APIs.-
Web API
are nothing but interfaces that allows JS code to interact with the browser environment and outside world. - Examples -
Fetch API
,Console API
,WebSocket API
,Storage API
-
- Queues
- MicroTask Queue : It is a special queue that hold microtasks that are scheduled to run right after the current call stack is empty, but before any macrotasks like
setTimeout,setInterval
.- It contains Promises.then , Promises.finally , Promises.catch.
- MacroTask Queue : It is the queue in which callbacks from the async code are stored that will be executed after the microtask is empty.
- It contains setTimeout , setTimeInterval , fetch , DOM events , file operations, IO operations etc.
- MicroTask Queue : It is a special queue that hold microtasks that are scheduled to run right after the current call stack is empty, but before any macrotasks like
Flow
- The sync. code is executed in the call stack.
- when the stack is empty, execute the task in the
microtask queue
. - Once the
microtask task is empty
, execute a task from themacrotask queue
. - Repeat 2 & 3.
// 1. Call stack + Macrotask queue console.log("1"); setTimeout(()=>{ console.log("2"); },0) console.log("3"); // Output : 1 3 2 // 2. call stack + Micro & macro task queue console.log("1"); setTimeout(()=>{ console.log("2"); },0) Promise.resolve().then(()=>{ console.log("3"); }) console.log("4"); // Output : 1 4 3 2 // 3. Micro Task creating more microtask console.log("1"); setTimeout(()=>{ console.log("2"); },0) Promise.resolve().then(()=>{ console.log("3"); Promise.resolve().then(()=>{ console.log("4"); }) }) console.log("5"); // OUTPUT : 1 ,5,3,4,2 // 4. MIX console.log("Start"); setTimeout(() => { console.log("Timeout 1"); }, 0); Promise.resolve() .then(() => { console.log("Promise 1"); setTimeout(() => { console.log("Timeout 2"); }, 0); }); setTimeout(() => { console.log("Timeout 3"); }, 0); console.log("End"); // OUTPUT // Start // End // Promise 1 // Timeout 1 // Timeout 3 // Timeout 2
useCallBack
It is React Hook
that returns a memoized function.
Memoized Function : A Function that is cached and is not recreated on every render.
The function will only be recreated when the dependencies change.
const handleClick = useCallback(() => { // do something }, [dependencies]); // This function will only be recreated when the dependencies change. // If the dependencies are empty, the function will never be recreated, unless it is unmount and remounted. const handleClick = useCallback(() => { // do something }, []);
Problem with useCallBack
- It can store the stale data.
const [count, setCount] = useState(0); // This will store the stale data. const handleClick = useCallback(() => { console.log(count); }, []); // FIX - 1 const handleClick = useCallback(() => { console.log(count); }, [count]); // FIX - 2 // if we pass the handleClick function to child component, so event time function is recreated the component rerendered to change this we use ref. const countRef = useRef(count); useEffect(()=>{ countRef.current = count; },count) const handleClick = useCallback(() => { console.log(count); }, []);
useMemo
It is a React Hook
that returns a memoized value.
// It returns a memoized value rather than a memozied function. const memoizedValue = useMemo(() => { // Expensive computation return result; }, [dependencies]); // Here is a memoized function using useMemo const handleClick = useMemo(()=>()=>{ setCount(count+1); },[count])
React.memo
It is a Higher Order Component
that memoizes the component.It prevents the components from rerendering unless the props are changed.
// On Every Render it compares the prv prop values with newer value, It only do shallow comparison. const MyComponent = React.memo((props) => { // Component code });
Problems with React.memo
- if the props are objects , array & function, then if different refernce is passed it will cause rerender.
- It only checks for props, not for state & context.
useRef
It is a React Hook
that returns a mutable ref object that persists across rerenders.
Use it when the value is not rendering in the UI and you don't want to trigger any re-render.
Some UseCase
- SetTimeout , SetTimeInterval
- keeping previous values
- creating flag or cache
const ref = useRef(0); // Access it using console.log(ref.current); // Modify it using , also updating it doesn't cause re-render. ref.current = 10; // We can attach it to DOM element to access them directly. const inputRef = useRef(null); // Get value : inputRef.current.value // Set value : inputRef.current.value = "Hello" // Focus : inputRef.current.focus() // Blur : inputRef.current.blur() <input ref={inputRef} />
It can use to presists values across re-renders. It will useful for timers or intervals, to store timeIDs
const timerRef = useRef(); function startInterval(){ timerRef = setInterval(()=>{ // do something },[3000]) } function removeInterval(){ clearInterval(timeRef); }
# Storing previous State
function prevState(){ const [count,setCount] = useState(0); const counRef = useRef(); const handleClick = ()=>{ setCount((prev)=>prev+1); } // will 1st run after render useEffect(()=>{ // doesn't cause rerender countRef.current = count; },[count]) return <> <h1>Current State : {count}</h1> <h1>Previous State : {countRef.current} </h1> <button onClick={handleClick}>Increment Count</button> </> } // Flow // Component Mounts // count = 0 & countRef = undefined [DISPLAYING THIS] // useEffect Runs // count = 0 & countRed=f = 0; // Increment the state // count = 1 // Rerender happens // count = 1 & countRef = 0 [DISPLAYING THIS] // useEffect Runs // count 1 & counte=Ref = 1
useRef doesn't cause component re-rendering, so if we are using it in a component, its value will not displayed
useEffect
It is a React Hook
that lets you perform side effect in functional components.
side effects
are the operations that effects things outside the scope of the component.
For example:
Fetching data from an API
Updating the DOM manually
Setting a timer
Subscribing to a WebSocket
Listening to window resize events
// Run for first time only useEffect(()=>{ // do something },[]) // Runs for first time and after that only when the count changes useEffect(()=>{ // do something },[count]) useEffect(()=>{ // runs before component unmount. return ()=>{ // do something } },[]) // Runs on every render useEffect(()=>{ // do something })
Top comments (0)