javascriptreactjsreact-router-domreact-toastify

React-toastify showing multiple toast


I am building a React app with several components and in at least half of them I am using React-notify and it's working properly in almost all of them except one. In this one when I trigger the toast I'm getting four toasts, one behind the other, but I believe they are not different toasts, since they have the same ID.

I found this thread https://github.com/fkhadra/react-toastify/issues/182, here the user was having the same issue as mine, the only exception is that I am not setting autoclose, he even provided a gif showing the problem:

https://i.sstatic.net/SiqRo.jpg

The solution according to this thread would be remove all <ToastContainer /> of the components and render it in the app root, which in my case is App.js. I did that, however the toasts are not being shown anymore, I don't know if I've done it right, though.

Besides that I also tried to set a custom ID and it didn't change anything.

I am using React-router-dom, maybe this is influencing in something, I couldn't find a proper answer nor in the documentation neither on any other source.

Here is simplified version of my App.js:

import Layout from './containers/Layout/Layout';

import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

import { BrowserRouter, Route, Switch } from 'react-router-dom';

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <Layout>
          <Switch>
            <Route path="/clientes" exact component={ClientesControls} />
            <Route path="/adm" exact component={AdmControls} />
            <Route path="/" component={OrcConfig} />
            <ToastContainer />
          </Switch>
        </Layout>
      </BrowserRouter>
    );
  }
}

Here is a sample of the componente whose bug is being generated:

import React from 'react';

import axios from '../../../axios';

import { toast } from 'react-toastify';

const listarProdutosItens = props => {
    
    const excluirItemHandler = i => {
        
        let key = props.listaItens[i].key
        let categoria = props.listaItens[i].categoria

        axios.delete(`/adm/${categoria}/${key}.json`)
            .then(res => {
                props.fetchLista()
                notify('excluído')
            })
            .catch(error => notify('não excluído'))
    }

    const notify = (arg) => {
        if (arg === 'excluído') {
            toast.success('Produto removido com sucesso')
            console.log('TESTE')
        } else if (arg === 'não excluído') {
            toast.error('Erro ao tentar remover produto')
        }
    }

    return (
        <div className="row border-bottom mt-2">
            <button onClick={() => excluirItemHandler(i)} ></button>
            {/* <ToastContainer /> */}
        </div>
    )

}

The components that are working properly have the same sintaxe.

Any help would be very appreciated.


Solution

  • Just move <ToastContainer /> outside of <Layout />