Without useMemo : infinite rerendering component
我在成功编译以下代码时遇到了问题,但是无限次地重新呈现组件,并且在控制台中收到以下错误:Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
import { Box, Flex } from "@chakra-ui/react";
import { useEffect, useState } from "react";
import Section, { SectionHeading } from "../../components/UI/Section";
import FaqList from "../../data/FaqList";
import FAQFilterBtn from "./FAQFilterBtn";
import FAQItems from "./FAQItems";
const allFaqItems = Object.values(FaqList).map((elem) => elem.content);
const allFaq = allFaqItems.map((elem, index) => (
<Box key={index}>
<FAQItems items={elem} faqHeading={Object.values(FaqList)[index].heading} />
</Box>
));
const FAQSection = () => {
const [displayList, setDisplayList] = useState(allFaq);
const [activeFilter, setActiveFilter] = useState("All");
const filteredAllFaq =
allFaqItems.map((elem, index) => {
const faq =
activeFilter === Object.values(FaqList)[index].heading ||
activeFilter === "All" ? (
elem.length ? (
<FAQItems
items={elem}
faqHeading={Object.values(FaqList)[index].heading}
/>
) : (
""
)
) : (
""
);
return <Box key={index}>{faq}</Box>;
});
const changeFilter = (filter: string) => {
setActiveFilter(filter);
};
useEffect(() => {
setDisplayList(filteredAllFaq);
}, [activeFilter, filteredAllFaq]);
console.log(activeFilter);
return (
<Section id="#faq-section">
<>
<Flex w="full" justify="space-between">
<SectionHeading mb={0}>Frequently asked questions</SectionHeading>
</Flex>
<Flex m={4} mb={-4} gap={6}>
<FAQFilterBtn
name="All"
active={activeFilter}
setFilter={changeFilter}
/>
{FaqList.map((e, index) => (
<FAQFilterBtn
key={index}
name={e.heading}
active={activeFilter}
setFilter={changeFilter}
/>
))}
</Flex>
{displayList}
</>
</Section>
);
};
export default FAQSection;
因此,我try 将useEffect
挂钩与更改筛选器(ActiveFilter)的依赖项一起使用,这将导致组件仅重新呈现一次,但它没有.我try 使用useCallback
挂钩,因为setState是异步的,但没有帮助.
With useMemo : issue seems "fixed"
然后我认为这与filteredAllFaq
是array.map()
有关,这可能是一个"昂贵/高负载的功能",所以我决定使用useMemo
挂钩,它似乎解决了这个问题.代码如下:
const filteredAllFaq = useMemo(() => allFaqItems.map((elem, index) => {
const faq =
activeFilter === Object.values(FaqList)[index].heading ||
activeFilter === "All" ? (
elem.length ? (
<FAQItems
items={elem}
faqHeading={Object.values(FaqList)[index].heading}
/>
) : (
""
)
) : (
""
);
return <Box key={index}>{faq}</Box>;
}), [activeFilter]);
const changeFilter = (filter: string) => {
setActiveFilter(filter);
};
useEffect(() => {
setDisplayList(filteredAllFaq);
}, [activeFilter, filteredAllFaq]);
console.log(activeFilter);
Even though it fixed the rerendering issue, I feel like I'm using it the wrong way and the whole component could be done much better.
There's also a small issue after my "fix" because it seems to render/console.log(activeFilter) exactly 4 times at mount and whenever 100 changes. I was expecting it to render only once.
我的react 是新的,以前从未用过useMemo
.我试着寻找解决办法,但我甚至不知道我的问题出在哪里.如有任何建议,我们将非常感激.谢谢