Search code examples
reactjsprimereact

Trigger toast from another React component


I'm using PrimeReact toast element.

The index.js file:

import Dialogs from './components/Dialogs';
import React, { useRef } from 'react';
import { Toast } from 'primereact/toast';

const Index = () => {

    const toast = useRef(null);

    ...

    return (
        <div className="card">
            <Toast ref={toast} />
            <Dialogs delete={delete} />
        </div>
    );
};

export default Status;

I want to trigger toast inside Dialogs.js (Dialogs) component:

import { Toast } from 'primereact/toast';
import React, { useRef } from 'react';

const Dialogs = ({delete}) => {
    const toast = useRef(null);

    return (
        <>
            <Toast ref={toast} />
        </>
    );
}

export default Dialogs;

if I remove <Toast ref={toast} /> from Dialogs component I get the error:

Uncaught TypeError: Cannot read properties of null (reading 'show')

How can I use <Toast ref={toast} /> defined in index.js but inside Dialogs component?


Solution

  • If the ref from Index (App in my example) just needs to be accessed as a trigger, simply passing it as a prop would work:

    App.js

    import Dialogs from "./Dialogs";
    import React, { useRef } from "react";
    import { Toast } from "primereact/toast";
    
    const App = () => {
      const toast = useRef(null);
    
      const onDelete = () => {
        toast.current.show({
          severity: "error",
          summary: "Deleted Message",
          detail: "Some message",
        });
      };
    
      const onClick = () => {
        toast.current.show({
          severity: "info",
          summary: "Info Message",
          detail: "Some information",
        });
      };
    
      return (
        <div>
          <button onClick={onClick}>trigger 1</button>
          <Toast ref={toast} />
          <Dialogs toast={toast} onDelete={onDelete} />
        </div>
      );
    };
    
    export default App;
    

    Dialogs.js

    import React from "react";
    
    const Dialogs = ({ onDelete, toast }) => {
      const onClick = () =>
        toast.current.show({
          severity: "success",
          summary: "Success Message",
          detail: "Order submitted",
        });
      return (
        <div>
          <button onClick={onClick}>trigger 2</button>
          <button onClick={onDelete}>trigger delete</button>
        </div>
      );
    };
    
    export default Dialogs;
    

    Here's a working sandbox example. If you need to move the <Toast> element into a sub-component and set the ref later on, you can wrap the component receiving the reference using Forwarding Refs.