Error
My next.js app use chakra-paginator, when I call toast on the page when is used chakra-paginator, browser console shows error:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method. ToastManager@http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1627303273546:38352:5
Find error
I find this bug, becouse when I removed all chakra-paginator components and hooks, Toast works OK.
Probably error only in Next.js
When I try it in codesandbox.io only in clear React + TS toast works ok. Problems is between chakra-paginator and next.js i think.
My code
import React, { FC, ChangeEvent, useEffect, useState } from "react";
import {
Grid,
Center,
Select,
ButtonProps,
Text,
Button,
useToast,
} from "@chakra-ui/react";
import {
Paginator,
Container,
Previous,
usePaginator,
Next,
PageGroup,
} from "chakra-paginator";
const fetchPokemons = (pageSize: number, offset: number) => {
return fetch(
`https://pokeapi.co/api/v2/pokemon?limit=${pageSize}&offset=${offset}`
).then((res) => res.json());
};
const Poke: FC = () => {
// react hooks
const [pokemonsTotal, setPokemonsTotal] = useState<number | undefined>(
undefined
);
const [pokemons, setPokemons] = useState<any[]>([]);
const toast = useToast();
// constants
const outerLimit = 2;
const innerLimit = 2;
const {
isDisabled,
pagesQuantity,
currentPage,
setCurrentPage,
setIsDisabled,
pageSize,
setPageSize,
offset, // you may not need this most of the times, but it's returned for you anyway
} = usePaginator({
total: pokemonsTotal,
initialState: {
pageSize: 10,
currentPage: 1,
isDisabled: false,
},
});
// effects
useEffect(() => {
fetchPokemons(pageSize, offset).then((pokemons) => {
setPokemonsTotal(pokemons.count);
setPokemons(pokemons.results);
});
}, [currentPage, pageSize, offset]);
// styles
const baseStyles: ButtonProps = {
w: 7,
fontSize: "sm",
};
const normalStyles: ButtonProps = {
...baseStyles,
_hover: {
bg: "green.300",
},
bg: "red.300",
};
const activeStyles: ButtonProps = {
...baseStyles,
_hover: {
bg: "blue.300",
},
bg: "green.300",
};
const separatorStyles: ButtonProps = {
w: 7,
bg: "green.200",
};
// handlers
const handlePageChange = (nextPage: number) => {
// -> request new data using the page number
setCurrentPage(nextPage);
console.log("request new data with ->", nextPage);
};
const handlePageSizeChange = (event: ChangeEvent<HTMLSelectElement>) => {
const pageSize = Number(event.target.value);
setPageSize(pageSize);
};
const handleDisableClick = () => {
return setIsDisabled((oldState) => !oldState);
};
return (
<>
<Paginator
isDisabled={isDisabled}
activeStyles={activeStyles}
innerLimit={innerLimit}
currentPage={currentPage}
outerLimit={outerLimit}
normalStyles={normalStyles}
separatorStyles={separatorStyles}
pagesQuantity={pagesQuantity}
onPageChange={handlePageChange}
>
<Container align="center" justify="space-between" w="full" p={4}>
<Previous>
Previous
{/* Or an icon from `react-icons` */}
</Previous>
<PageGroup isInline align="center" />
<Next>
Next
{/* Or an icon from `react-icons` */}
</Next>
</Container>
</Paginator>
<Center w="full">
<Button onClick={handleDisableClick}>Disable ON / OFF</Button>
<Select w={40} ml={3} onChange={handlePageSizeChange}>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
</Select>
</Center>
<Button
onClick={() => {
toast({
title: "new toast",
duration: 4000,
});
}}
>
Toast
</Button>
<Grid
templateRows="repeat(2, 1fr)"
templateColumns="repeat(5, 1fr)"
gap={3}
px={20}
mt={20}
>
{pokemons?.map(({ name }) => (
<Center p={4} bg="green.100" key={name}>
<Text>{name}</Text>
</Center>
))}
</Grid>
</>
);
};
export default Poke;
Toast doesnt works in this code in next.js, but in React.js it works.