Итак, пара вещей:
Вызывая toasts.set(id, <Toast {...{ message, color, duration, id }} />)
, вы напрямую изменяете свое состояние, чего вы не хотите делать. Затем вы вызываете setToasts
с тем же самым объектом Map
, чтобы он не запускал повторную визуализацию, поскольку это та же ссылка.
Кроме того, если это сработало, путем вызова createToast()
в ваш функциональный компонент во время его рендеринга вызвал бы исключение Maximum update depth exceeded
, как и:
- рендеринг
- создал тост, запускающий повторный рендеринг
- повторная визуализация
- создание тоста, запускающее повторную визуализацию
- повторная визуализация ... и так далее
Вы должны переместить создание тост, управляемый событиями, одним нажатием кнопки или чем-то, что имеет смысл.
Вы можете использовать Map
, но вам нужно будет сделать что-то вроде:
const [myMap, setMyMap] = useState(new Map());
const updateMap = (k,v) => {
setMyMap(new Map(myMap.set(k,v)));
}
как показано на https://medium.com/swlh/using-es6-map-with-react-state-hooks-800b91eedd5f. Это создаст новый объект Map
с парами ключ-значение текущего Map
.
В качестве альтернативы вы можете использовать объект {}
с парой настроек:
const toastState = useState({});
setToasts({
...toasts,
[id]: <Toast key={id} {...{ message, color, duration, id }} />
});
function ToastContainer (props) {
let [toasts, setToasts] = useContext(ToastContext)
return Object.values(toasts);
}
if (duration) {
setTimeout(() => {
const newToasts = { ...toasts };
delete newToasts[id];
}, duration * 1000)
}