From Harsh Makadia
1.useState Lazy Initializtion With Function
There are some times when we need to set the initial value of the state from some variable or from a function that returns a value.
// without lazy initializtion
const initialState = caculateWithValue(props)
const [count, setCount] = React.useState(initialState)
// with lazy initialization
const getInitialState = props => caculateWithValue(props)
const [count, setCount] = React.useState(getInitialState)
Since our function is in the body, every time a re-render happens, this function is getting called even if its value is not required (we only need it during the initial render).
2. Monitor Unnecessary Renders in Your Applications
One of the common problems we face is evaluating the necessary renders in your application that are having a bad impact on the performance.
github.com/welldone-so…
3. Using React.memo and useMemo
React.memo does a shallow comparison out of the box and avoids rendering. Memoizing the result will provide a performance boost. This means that React will skip rendering the component and reuse the last rendered result.
4. Deep Comparison in shouldComponentUpdate (Pure Component)
Compare two object, returning whether they are equal according to a recursive equality algorithm. This can be used in shouldComponentUpdate lifecycle and avoid some unnecessary re-rendering.
5. Use React Window
When the dropdown/table list grows long, the UI performance will be affected. It starts consuming a lot of memory in the browser. Since all the list items are in the DOM, there will be a lag when you scroll the list.
React window works by only rendering part of a large data set (just enough to fill the viewport). This helps address some common performance bottlenecks:
- It reduces the amount of work (and time) required to render the initial view and to process updates.
- It reduces the memory footprint by avoiding over-allocation of DOM nodes. github.com/bvaughn/rea…
6.Use React Query
Provides performant and powerful data synchronization for React. And can fetch, cache and update data in your React and React Native applications all without touching any "global state".
Some benefit:
- Transport/protocol/backend agnostic data fetching (REST, GraphQL, promises, whatever!)
- Auto Caching + Refetching (stale-while-revalidate, Window Refocus, Polling/Realtime)
- Parallel + Dependent Queries
- Mutations + Reactive Query Refetching
- Multi-layer Cache + Automatic Garbage Collection
- Paginated + Cursor-based Queries
- Load-More + Infinite Scroll Queries w/ Scroll Recovery
- Request Cancellation
- React Suspense + Fetch-As-You-Render Query Prefetching
- Dedicated Devtools
7. One Function to Update Multiple Input State Values
This is the common use case of keeping the same function to update multiple input values. Most of us know about this approach that helps to reduce the code and get our job done.
import React from 'react';
export const Form = () => {
const [state, setState] = React.useState({
firstName: '',
lastName: ''
})
// wrapper the common function to handle updating form values in the state
const handleChange = e => {
const value = e.target.value;
setState({
...state,
[e.target.name]: vaule
})
}
return (
<form>
<label>FirstName
<input
type='text'
name='firstName'
value={state.firstName}
onChange={handleChange}
/>
</label>
<label>LastName
<input
type='text'
name='lastName'
value={state.lastName}
onChange={handleChange}
/>
</label>
</form>
);
}
8. Making Use of Custom Hooks
Sometimes, we wanna execute some callbacks after setState. In this case, we can use custom hooks to wrapper the common logic and reduce the teadious template code.
const App = () => {
const [state, setState] = useStateCallback(0); // same API as useState + setState with callback
const handleClick = () => {
setState(
prev => prev + 1,
//2nd argument is callback, and 's' is the updated state
//after setState set successfully, the callback will be executed subsequently.
s => console.log("Callbacks executed after setState, state: ", s)
);
);
return <button onClick={handleClick}>Increment</button>;
}
export const useStateCallback(initialState) {
const [state, setState] = useState(initialState);
const callbackRef = useRef(null);
const setStateCallback = (state, cb) => {
cb.current = cb; // store the passed callback to ref
setState(state);
}
useEffect(() => {
//cb.current is 'null' on initial render, so only execute cb on state *updates*
if(cb.current) {
cbRef.current(state);
cbRef.current = null; // reset callback after execution
}
}, [state]};
return [state, setStateCallback];
}
9. Lazy Loading React Components
Lazy loading is the technique of rendering only needed or critical user interface items first, then quietly unrolling the non-critical items later. The React.lazy function lets you render a dynamic import as a regular component.
10. Pause Console Debugger
This is a lifesaver tip: Freeze dropdown in browser to inspect it properly. If you have an element that keeps disappearing on you, just execute 'debugger' from your console to halt javaScript so you can target the element.
setTimeout(() => {debugger;}, 5000)