0% found this document useful (0 votes)
51 views

React Cheat Sheet

This document discusses different ways to manage state and handle side effects in React components. It compares using the useState hook, useReducer hook, class components, and useEffect hook. It also introduces useLayoutEffect which is similar to useEffect but fires synchronously after render to safely read/write to the DOM.

Uploaded by

Jatin Parmar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
51 views

React Cheat Sheet

This document discusses different ways to manage state and handle side effects in React components. It compares using the useState hook, useReducer hook, class components, and useEffect hook. It also introduces useLayoutEffect which is similar to useEffect but fires synchronously after render to safely read/write to the DOM.

Uploaded by

Jatin Parmar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

MANAGE STATE • Hook Way

import { useState } from "react";


useState
const initialCount = 0;
function Counter() {
const [count, setCount] = useState(initialCount); const [count, setCount] = useState(initialCount);
return (
<div>
• Class way <p>You clicked {count} times</p>
<button
const initialCount = 0; onClick = {() => setCount((c) => c + 1)}
class Counter extends Component { >
constructor(props) { Click me
super(props); </button>
this.state = { count : initialCount }; </div>
} );
render() { }
return (
<div>
<p>You clicked {this.state.count} times</p>
<button useReducer
onClick = {() => this.setState(({count}) => ({ count: count + 1 }))}
>
const [state, dispatch] = useReducer(
Click me
reducer,
</button>
initialState,
</div>
initialDispatch
);
);
}
}
An alternative to useState. Use it in the components that need
complex state management, such as multiple state values being
updated by multiple methods.

3|Page 4|Page
• Class way
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) { class FriendStatus extends React.Component {
case 'increment': state = { isOnline : null };
componentDidMount() {
return {count: state.count + 1};
ChatAPI.subscribeToFriendStatus(
case 'decrement':
this.props.friend.id,
return {count: state.count - 1};
this.handleStatusChange
default: );
throw new Error(); }
} componentWillUnmount() {
} ChatAPI.unsubscribeFromFriendStatus(
function Counter({initialState}) { this.props.friend.id,
const [state, dispatch] = useReducer(reducer, initialState); this.handleStatusChange
return ( );
<> }
Count: {state.count} componentDidUpdate(prevProps) {
<button onClick = {() => dispatch({type: 'increment'})}>+</button> if(this.props.friend.id !== prevProps.id) {
ChatAPI.unsubscribeFromFriendStatus(
<button onClick = {() => dispatch({type: 'decrement'})}>+</button>
prevProps.friend.id,
</>
this.handleStatusChange
);
);
} ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
HANDLE SIDE EFFECTS }
}

handleStatusChange = status => {


useEffect this.setState({
isOnline: status.isOnline
});
useEffect(() => { }
applyEffect(dependencies); render() {
return () => cleanupEffect(); if (this.state.isOnline === null) {
}, [dependencies]); return 'Loading...';
}
return this.state.isOnline ? 'Online' : 'Offline';
}
}

5|Page 6|Page
• Hook Way useLayoutEffect is almost same as useEffect, but fires
synchronously after the render phase. Use this to safely read from
import { useState, useEffect } from 'react';
function FriendStatus(props) { or write to the DOM
const [isOnline, setIsOnline] = useState(null);
status
import { useRef, useLayoutEffect } from "react";
const handleStatusChange = (status) => setIsOnline(status.isOnline);
useEffect( function ColoredComponent({color}) {
const ref = useRef();
() => {
// Update status when the listener triggers useLayoutEffect(() => {
ChatAPI.subscribeToFriendStatus( const refColor = ref.current.style.color;
props.friend.id, console.log(`${refColor} will always be the same as ${color}`);
handleStatusChange ref.current.style.color = "rgba(255,0,0)";
}, [color]);
);
// Stop listening to status changes every time we cleanup useEffect(() => {
return function cleanup() { const refColor = ref.current.style.color;
console.log(
ChatAPI.unsubscribeFromFriendStatus(
`but ${refColor} can be different from ${color} if you play with the
props.friend.id,
handleStatusChange DOM`
); );
}; }, [color]);
}, return (
[props.friend.id] // Cleanup when friend id changes or when we "unmount" <div ref={ref} style={{ color: color }}>
); Hello React hooks !
if (isOnline === null) { </div>
return 'Loading...'; );
}
}
return isOnline ? 'Online' : 'Offline';
}
<ColoredComponent color = {"rgb(42, 13, 37)"}/>
// rgb(42, 13, 37) will always be the same as rgb(42, 13, 37)
// but rgb(255, 0, 0) can be different from rgb(42, 13, 37) if you play with the DOM
useLayoutEffect

useLayoutEffect(() => {
applyBlockingEffect(dependencies);
return cleanupEffect();
}, [dependencies]);

7|Page 8|Page
USE THE CONTEXT API • Hook Way

import { useContext } from 'react';


useContext function Header() {
const { handleLogin, isLoggedIn} = useContext(AuthContext);
const { isOpen, showModal, hideModal } = useContext(ModalContext);
const ThemeContext = React.createContext(); const { notification, notify } = useContext(NotificationContext);
const contextValue = useContext(ThemeContext);
return ...
}
• Class way
NOTE: Use the created context, not the consumer.
class Header extends React.Component {
const Context = React.createContext(defaultValue);
public render() {
// Wrong
return (
const value = useContext(Context.Consumer);
<AuthContext.Consumer>
// Right
{({ handleLogin, isLoggedIn}) => (
const value = useContext(Context);
<ModalContext.Consumer>
{({ isOpen, showModal, hideModal }) => (
<NotificationContext.Consumer>
{({ notification, notify }) => {
return (
MEMOIZE EVERYTHING
...
) useMemo
}}
</NotificationContext.Consumer>
)} const memoizedValue = useMemo (
</ModalContext.Consumer> () => expensiveFn (dependencies),
)} [dependencies]
</AuthContext.Consumer> );
);
}
}

9|Page 10 | P a g e
function RandomColoredLetter(props) { USE REFS
const [color, setColor] = useState('#fff')
const [letter, setLetter] = useState('a')
useRef
const handleColorChange = useMemo(() => () =>
setColor(randomColor()), []);
const handleLetterChange = useMemo(() => () => const ref = useRef();
setLetter(randomColor()), []);
return (
<div> useRef can just be used as a common React ref :
<ColorPicker handleChange={handleColorChange} color={color} />
<LetterPicker handleChange={handleLetterChange} letter={letter} /> import { useRef } from "react";
<hr/> function TextInput() {
<h1 style={{color}}>{letter}</h1> const inputRef = useRef(null);
</div> const onBtnClick = () => inputRef.current.focus();
) return (
} <>
<input ref={ref} />
<button onClick={onBtnClick}>Focus the text input</button>
useCallback </>
)
}
const memoizedCallback = useCallback (
expensiveFn (dependencies),
[dependencies] But it also allows you to just hold a mutable value through any
);
render. Also, mutating the value of ref.current will not cause any

function RandomColoredLetter(props) { render.


const [color, setColor] = useState('#fff')
const [letter, setLetter] = useState('a')
const handleColorChange = useCallback(() => setColor(randomColor()), []); useImperativeHandle
const handleLetterChange = useCallback(() => setLetter(randomColor()), []);
return (
useImperativeHandle (
<div>
ref,
<ColorPicker handleChange={handleColorChange} color={color} />
<LetterPicker handleChange={handleLetterChange} letter={letter} /> createHandle,
<hr/> [dependencies]
<h1 style={{color}}>{letter}</h1> )
</div>
)
}

11 | P a g e 12 | P a g e
useImperativeHandle allows you to customize the exposed interface
REUSABILITY
of a component when using a ref. The following component will
automatically focus the child input when mounted : Extract reusable behaviour into custom hooks.

import { useState, useRef, useCallback, useEffect } from "React";


function TextInput(props, ref) { // let's hide the complexity of listening to hover changes
const inputRef = useRef(null); function useHover() {
const onBtnClick = () => inputRef.current.focus(); const [value, setValue] = useState(false); // store the hovered state
useImperativeHandle(ref, () => ({ const ref = useRef(null); // expose a ref to listen to
focusInput: () => inputRef.current.focus(); // memoize function calls
}); const handleMouseOver = useCallback(() => setValue(true), []);
return ( const handleMouseOut = useCallback(() => setValue(false), []);
<Fragment> // add listeners inside an effect,
<input ref={inputRef} /> // and listen for ref changes to apply the effect again
<button onClick={onBtnClick}>Focus the text input</button> useEffect(() => {
</Fragment> const node = ref.current;
) if (node) {
} node.addEventListener("mouseover", handleMouseOver);
const TextInputWithRef = React.forwardRef(TextInput); node.addEventListener("mouseout", handleMouseOut);
function Parent() { return () => {
const ref = useRef(null); node.removeEventListener("mouseover", handleMouseOver);
useEffect(() => { node.removeEventListener("mouseout", handleMouseOut);
ref.focusInput(); };
}, []); }
return ( }, [ref.current]);
<div> // return the pair of the exposed ref and it's hovered state
<TextInputWithRef ref={ref} /> return [ref, value];
</div> }
);
}

const HoverableComponent = () => {


const [ref, isHovered] = useHover();
return (
<span style={{ color: isHovered ? "blue" : "red" }} ref={ref}>
Hello React hooks !
</span>
);
};

13 | P a g e 14 | P a g e

You might also like