11

I've written the following hook for alert boxes:

import MuiAlert from '@material-ui/lab/Alert';
import { Snackbar } from '@material-ui/core';
import React from 'react';

export const useAlert = () => {
    const [open, setOpen] = React.useState(false);
    const [message, setMessage] = React.useState('');

    const openAlert = (message) => {
        setOpen(true);
        setMessage(message);
    };

    const closeAlert = (event, reason) => {    
        setOpen(false);
    };

    return {
        openAlert,
        Alert: <Snackbar open={open} onClose={closeAlert}><MuiAlert onClose={closeAlert}>{ message }</MuiAlert></Snackbar>
    };
};

and I integrate this hook into other functional components as so:

import { useAlert } from './useAlert';

const Dashboard = () => {
    const { openAlert, Alert } = useAlert();
    return (
        <div>{ Alert }</div>
    )
};

I know that it's bad practice to return functional components from React hooks since the hook will produce a new instance of the component on every render.

However, here, I'm returning a JSX element and not a component. Is this still bad practice?

mitmath514
  • 347
  • 1
  • 4
  • 9

1 Answers1

14

Returning JSX from custom hooks is kind of an anti patterns. While it works there is little reason to return JSX from custom hooks.

A function returning JSX can simply be converted to a functional component with hooks. Writing it down as a component will help you in a number of ways

  • Provides flexibility to pass down props to control behaviors easily
  • Also its easier to memoize functional components to prevent additional renders if nothing has changed. You can do so with custom hooks too but then you will have to make use of useMemo
  • It makes it easier to define a clear hierarchy of elements.
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400