Introduction To React Hooks
Introduction To React Hooks
Q2:
How to access DOM elements in React?
Answer
One of the useful application of the useRef() hook is to access DOM elements. This is performed in 3
steps:
Consider:
function AccessingElement() {
useEffect(() => {
const divElement = elementRef.current;
console.log(divElement); // logs <div>I'm an element</div>
}, []);
return (
<div ref={elementRef}>
I'm an element
</div>
);
}
Q3:
How to call loading function with React useEffect only
once?
Answer
If you only want to run the function given to useEffect after the initial render, you can give it an empty
array [] as the second argument.
For example:
function MyComponent(){
useEffect(() => {
loadDataOnlyOnce();
}, []);
Q4:
Provide an example of any simple Custom React
Hook. Why do we need Custom Hooks?
Answer
A Custom Hook is a stateful function that uses other react built-in hooks
(e.g. useState, useCallback etc.) that can wrap around the stateful logic that you wanted to gather in
one place and avoid copying and pasting the same logic in multiple components.
Consider the increment/decriment custom hook:
return {
counter, // counter value
increment: () => setCounter(counter + 1), // function 1
decrement: () => setCounter(counter - 1) // function 2
};
};
and then in your component you can use it as follows:
return (
<div>
<span onClick={decrement}>-</span>
<span style={{ padding: "10px" }}>{counter}</span>
<span onClick={increment}>+</span>
</div>
);
}
Problem
Explain what is the use of useState(0) there:
...
const [count, setCounter] = useState(0);
const [moreStuff, setMoreStuff] = useState(...);
...
Q6:
Can you initialise state from a function? Provide and
example
Mid
React Hooks 46
Answer
Yes! Consider:
const StateFromFn = () => {
const [token] = useState(() => {
let token = window.localStorage.getItem("my-token");
return token || "default#-token#"
})
React Hooks 46
Answer
No. Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and
remembering the current value), but every time you use a custom Hook, all state and effects
inside of it are fully isolated.
Q8:
Explain the difference between useState and useRef hooks?
Mid
React Hooks 46
Answer
1. Updating a reference created by useRef doesn't trigger re-rendering, while updating the state
(setState) makes the component re-render;
2. useRef returns an object with a current property holding the actual value. In
contrast, useState returns an array with two elements.
3. useRef‘s current property is mutable, but useState‘s state variable is not.
4. The reference update is synchronous (the updated reference value is available right away),
while the state update is asynchronous (the state variable is updated after re-rendering).
Q9:
How can I make use of Error Boundaries in functional
React components?
Mid
React 130
Answer
As of v16.2.0, there's no way to turn a functional component into an error boundary.
The componentDidCatch() method works like a JavaScript catch {} block, but for components. Only
class components can be error boundaries. In practice, most of the time you’ll want to
declare an error boundary component once and use it throughout your application.
Also bear in mind that try/catch blocks won't work on all cases. If a component deep in the
hierarchy tries to update and fails, the try/catch block in one of the parents won't work -- because it
isn't necessarily updating together with the child.
A few third party packages on npm implement error boundary hooks.
Q10:
How to use componentWillMount() in React Hooks?
Mid
React Hooks 46
Answer
You cannot use any of the existing lifecycle methods
(componentDidMount, componentDidUpdate, componentWillUnmount etc.) in a hook. They can only be
used in class components. And with Hooks you can only use in functional components.
You can think of useEffect Hook as componentDidMount, componentDidUpdate,
and componentWillUnmount combined.
1. Code inside componentDidMount run once when the component is mounted. useEffect hook
equivalent for this behaviour is
2. useEffect(() => {
3. // Your code here
}, []);
4. Without the second parameter the useEffect hook will be called on every render
(like componentDidUpdate) of the component which can be dangerous:
5. useEffect(() => {
6. // Your code here
});
7. Hook equivalent of componentWillUnmount() code will be as follows
8. useEffect(() => {
9. window.addEventListener('mousemove', () => {});
10.
11. // returned function will be called on component unmount
12. return () => {
13. window.removeEventListener('mousemove', () => {})
14. }
}, [])
Q11:
What are common use cases for the useMemo?
Mid
React Hooks 46
Answer
The primary purpose of useMemo hook is "performance optimization".
• referential equality of the values (to further send them to props of the components to
potentially avoid re-renders)
• eliminate redoing of the computationally expensive operations for same parameters
For example:
function App() {
const [data, setData] = useState([....]);
function format() {
console.log('formatting....'); // this will print only when data has changed
const formattedData = [];
data.forEach(item => {
const newItem = //...do soemthing here,
if (newItem) {
formattedData.push(newItem);
}
})
return formattedData;
}
return (
<>
{formattedData.map(item => (
<div key={item.id}>
{item.title}
</div>
))}
</>
)
}
Q12:
What are differences between React.memo() and useMemo()?
Mid
React Hooks 46
Answer
Q13:
What are production use cases for the useRef?
Mid
React Hooks 46
Answer
For example:
Q14:
What is equivalent of this code using React Hooks?
Mid
React 130
Problem
Let's say in our project we have componentWillUnmount that is used for cleanup (like removing
event listeners, cancel the timer etc). How to refactor this code using React Hooks?
componentDidMount() {
window.addEventListener('mousemove', () => {})
}
componentWillUnmount() {
window.removeEventListener('mousemove', () => {})
}
Answer
React Hooks equivalent of above code will be as follows
useEffect(() => {
window.addEventListener('mousemove', () => {});
React Hooks 46
Answer
React’s useContext hook makes it easy to pass data throughout your app without manually
passing props down the tree. React Context is a way to manage state globally.
Consider:
return (
<UserContext.Provider value={user}>
<h1>{`Hello ${user}!`}</h1>
<Component2 user={user} />
</UserContext.Provider>
);
}
Then you can access the user Context in all components:
import { useState, createContext, useContext } from "react";
function Component5() {
const user = useContext(UserContext);
return (
<>
<h1>Component 5</h1>
<h2>{`Hello ${user} again!`}</h2>
</>
);
}
Q16:
When would you use useRef?
Mid
React Hooks 46
Answer
The main use cases:
1. To store a ref to DOM elements so you can later do something with them:
Consider:
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text"/>
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
Consider:
function Counter(){
const [count, setCount] = useState(0);
Q17:
When writing a Custom Hook, what is the difference
between it and a normal function?
Mid
React Hooks 46
Answer
Hooks use a stateful closure around the invocation of the function component to store the state on
behalf of that component instance. That closure is maintained by React.
• Custom hook will only be "stateful" if you use state with useState inside (or something that
implements useState),
• Hooks should be called from the React code only not from the regular JS functions. Hence,
Hooks' scope is limited to the React code world and has more power to do a lot with React
code,
• In the class-based components, the Hooks won't work but regular functions will.
• In the regular JS functions, you can't access useState, useEffect, useContext etc. but in react
custom hooks I can.
Q19:
Do Hooks replace render props and higher-order
components (HOC)?
Senior
React Hooks 46
Answer
Often, render props and higher-order components render only a single child. React team
thinks Hooks are a simpler way to serve this use case.
There is still a place for both patterns (for example, a virtual scroller component might have a
renderItem prop, or a visual container component might have its own DOM structure). But in most
cases, Hooks will be sufficient and can help reduce nesting in your tree.
Q20:
How do I update state on a nested
object with useState()?
Senior
React Hooks 46
Problem
I have a component that receives a prop that looks like this:
const styles = {
font: {
size: {
value: '22',
unit: 'px'
},
weight: 'bold',
color: '#663300',
family: 'arial',
align: 'center'
}
};
How to update only the align property?
Answer
You need to use spread syntax. Also while trying to update current state based on previous, use
the callback pattern os setState:
const { ...styling } = styles;
const [style, setStyle] = useState(styling);
...
setStyle(prevStyle => ({
...prevStyle,
font: { ...prevStyle.font, align: event.target.value }
}));
Q21:
How to mitigate multiple component re-renders when
using multiple useState calls?
Senior
React 130
Problem
Consider this code:
useEffect(async () => {
if(test.ok){
setLoading(false);
setData(test.data.results);
}
}, []);
Answer
1. You could combine the loading state and data state into one state object and then you could
do one setState call and there will only be one render.
Consider:
useEffect(() => {
// Note that this replaces the entire object and deletes user key!
setUserRequest({ loading: true });
fetch('https://randomuser.me/api/')
.then(results => results.json())
.then(data => {
setUserRequest({
loading: false,
user: data.results[0],
});
});
}, []);
2. Before React 18, React will batch state updates if they're triggered from within a React-
based event, like a button click or input change. It will not batch updates if they're triggered
outside of a React event handler, like an async call.
3. Starting in React 18 (opt-in feature) all updates will be automatically batched, no matter
where they originate from.
4. Q22:
5. Provide a good example of using useCallback hook in
React
6. Senior
7.
8. React Hooks 46
9.
10. Answer
11. Imagine you have a component that renders a big list of items. To prevent useless list re-
renderings, you wrap it into React.memo().
12. import useSearch from './fetch-items';
13. function MyBigList({ term, onItemClick }) {
14. const items = useSearch(term);
15. const map = item => <div onClick={onItemClick}>{item}</div>;
16. return <div>{items.map(map)}</div>;
17. }
18. export default React.memo(MyBigList);
19. The parent component of MyBigList provides a handler function to know when an item is
clicked:
20. import { useCallback } from 'react';
21.
22. export function MyParent({ term }) {
23. const onItemClick = useCallback(event => {
24. console.log('You clicked ', event.currentTarget);
25. }, [term]);
26. return (
27. <MyBigList
28. term={term}
29. onItemClick={onItemClick}
30. />
31. );
32. }
33. onItemClick callback is memoized by useCallback(). As long as term is the
same, useCallback() returns the same function object that passed to NyBigList as a prop.
When MyParent component re-renders, onItemClick function object remains the
same and doesn't break the memoization of MyBigList. That's the right use case to
use useCallback.
34.
Q23:
What's the difference between useCallback and useMemo in
practice?
Senior
React 130
Answer
With useCallback you memoize functions, useMemo memoizes any computed value:
const fn = () => 42 // assuming expensive calculation here
const memoFn = useCallback(fn, [dep]) // (1)
const memoFnReturn = useMemo(fn, [dep]) // (2)
(1) will return a memoized version of fn - same reference across multiple renders, as long
as dep is the same. But every time you invoke memoFn, that complex computation starts again.
(2) will invoke fn every time dep changes and remember its returned value (42 here), which is
then stored in memoFnReturn.
Q24:
When would you use flushSync in ReactJS?
Senior
React 130
Answer
React 18 adds out-of-the-box performance improvements by doing more batching (automated) by
default. Batching is when React groups multiple state updates into a single re-render for better
performance.
• To opt-out of automatic batching, you can use flushSync so your component will be re-
rendered after each state update. You might need it when for example some code may
depend on reading something from the DOM immediately after a state change.
function handleClick() {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
}
Consider with flushSync:
import { flushSync } from 'react-dom';
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// React has updated the DOM by now
flushSync(() => {
setFlag(f => !f);
});
// React has updated the DOM by now
}