React-toastify показывает несколько тостов

Я создаю приложение React с несколькими компонентами, и по крайней мере в половине из них я использую React-notifyи он работает нормально почти во всех, кроме одного. В этом случае, когда я запускаю тост, я получаю четыре тоста, один за другим, но я считаю, что это не разные тосты, поскольку у них одинаковый идентификатор.

Я нашел этот поток https://github.com/fkhadra/react-toastify/issues/182, здесь у пользователя была та же проблема, что и у меня, единственное исключение - я не устанавливаюautoclose, он даже предоставил гифку, показывающую проблему:

https://imgur.com/a/8NMMaRa

Решение в соответствии с этой веткой - удалить все <ToastContainer /> компонентов и отобразить его в корне приложения, что в моем случае App.js. Я так и сделал, но тосты больше не показываются, хотя я не знаю, правильно ли я сделал.

Кроме того, я также пытался установить собственный идентификатор, но это ничего не изменило.

Я использую React-router-dom, может это на что-то влияет, я не нашел ни правильного ответа, ни документации ни по какому-либо другому источнику.

Вот упрощенная версия моего 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>
    );
  }
}

Вот образец компонента, ошибка которого генерируется:

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>
    )

}

Компоненты, которые работают правильно, имеют одинаковый синтаксис.

Любая помощь будет очень признательна.

8 ответов

Решение

Просто двигайся <ToastContainer /> снаружи <Layout />

У меня была такая же проблема (и моя уже была вне маршрутизатора). Это, вероятно, не решает основную проблему, но у меня сработало добавление пользовательского идентификатора тоста, то есть изменение

      toast.success('Produto removido com sucesso')

к

      toast.success('Produto removido com sucesso', {
    toastId: 'success1',
})

и повторяющиеся тосты больше не появлялись.

Переместите <ToastContainer/> где угодно за пределами <Switch>, потому как:

<Switch> уникален тем, что отображает исключительно маршрут.

Также:

Все дети <Switch> должно быть <Route> или <Redirect>элементы. Будет отображен только первый дочерний элемент, соответствующий текущему местоположению.

См.: https://reacttraining.com/react-router/web/api/Switch

импортируйте тост в свой компонент, в который вы добавили логику тостера ex. нижеприведенный:

      import { toast } from 'react-toastify';
// avoid the ToastContainer to add here and the css as well

Затем в корне вашего приложения:

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

const CommonComponent = () => (
  <div>
    <ToastContainer />
    <OtherComponent />
  </div>
)

добавить идентификатор тоста:

      toast.success('Produto removido com sucesso', {
    toastId: 'success1',
})
      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')
    }
}

К

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

Просто используйте собственный toastId, и он решит вашу проблему!

Также обязательно нужно проверить, что в вашем коде нет множественных<ToastContainer/>в разных местах вашего приложения

Просто добавьlimit={1}кToastContainer. Так:

      <ToastContainer limit={1}>

Ссылка: https://fkhadra.github.io/react-toastify/limit-the-number-of-toast-displayed/

Другие вопросы по тегам