๐
React Hook Pitfalls
Table of contents
List some common use hooks pitfall here.
Using useState when no rerender is needed
Should not ๐ ๐ฝ
jsx
function ClickButton(props) {const [count, setCount] = useState(0);const onClickCount = () => {setCount((c) => c + 1);};const onClickRequest = () => {apiCall(count);};return (<div><button onClick={onClickCount}>Counter</button><button onClick={onClickRequest}>Submit</button></div>);}
Should ๐
jsx
function ClickButton(props) {const count = useRef(0);const onClickCount = () => {count.current++;};const onClickRequest = () => {apiCall(count.current);};return (<div><button onClick={onClickCount}>Counter</button><button onClick={onClickRequest}>Submit</button></div>);}
Using router.push instead of a link
Should not ๐ ๐ฝ
jsx
function ClickButton(props) {const history = useHistory();const onClick = () => {history.push("/next-page");};return <button onClick={onClick}>Go to next page</button>;}
Should ๐
jsx
function ClickButton(props) {return (<Link to="/next-page"><span>Go to next page</span></Link>);}
Handling actions via useEffect
Should not ๐ ๐ฝ
jsx
function DataList({ onSuccess }) {const [loading, setLoading] = useState(false);const [error, setError] = useState(null);const [data, setData] = useState(null);const fetchData = () => {setLoading(true);callApi().then((res) => setData(res)).catch((err) => setError(err)).finally(() => setLoading(false));};useEffect(() => {fetchData();}, []);useEffect(() => {if (!loading && !error && data) {onSuccess();}}, [loading, error, data, onSuccess]);return <div>Data: {data}</div>;}
Should ๐
jsx
function DataList({ onSuccess }) {const [loading, setLoading] = useState(false);const [error, setError] = useState(null);const [data, setData] = useState(null);const fetchData = () => {setLoading(true);callApi().then((fetchedData) => {setData(fetchedData);onSuccess();}).catch((err) => setError(err)).finally(() => setLoading(false));};useEffect(() => {fetchData();}, []);return <div>{data}</div>;}
Single responsibility components
Should not ๐ ๐ฝ
jsx
function Header(props) {return (<header><HeaderInner menuItems={menuItems} /></header>);}function HeaderInner({ menuItems }) {return isMobile() ? (<BurgerButton menuItems={menuItems} />) : (<Tabs tabData={menuItems} />);}
Should ๐
jsx
function Header(props) {return (<header>{isMobile() ? (<BurgerButton menuItems={menuItems} />) : (<Tabs tabData={menuItems} />)}</header>);}
Single responsibility useEffects
Should not ๐ ๐ฝ
jsx
function Example(props) {const location = useLocation();const fetchData = () => {/* Calling the api */};const updateBreadcrumbs = () => {/* Updating the breadcrumbs*/};useEffect(() => {fetchData();updateBreadcrumbs();}, [location.pathname]);return (<div><BreadCrumbs /></div>);}
Should ๐
jsx
function Example(props) {const location = useLocation();const updateBreadcrumbs = () => {/* Updating the breadcrumbs*/};useEffect(() => {updateBreadcrumbs();}, [location.pathname]);const fetchData = () => {/* Call the api */};useEffect(() => {fetchData();}, []);return (<div><BreadCrumbs /></div>);}