React useEffect-在依赖项数组中传递函数

时间:2020-06-26 19:21:48

标签: reactjs react-hooks use-effect usecallback

当我将函数表达式传递给useEffect依赖数组时,为什么会创建无限循环?函数表达式不会更改组件状态,它仅引用它。

// component has one prop called => sections

const markup = (count) => {
    const stringCountCorrection = count + 1;
    return (
        // Some markup that references the sections prop
    );
};

// Creates infinite loop
useEffect(() => {
    if (sections.length) {
        const sectionsWithMarkup = sections.map((section, index)=> markup(index));
        setSectionBlocks(blocks => [...blocks, ...sectionsWithMarkup]);
    } else {
        setSectionBlocks(blocks => []);
    }
}, [sections, markup]);

如果标记更改了状态,我可以理解为什么它会创建一个无限循环,但它不仅仅引用prop节。

对于那些寻求解决此问题的人

const markup = useCallback((count) => {
        const stringCountCorrection = count + 1;
        return (
            // some markup referencing the sections prop
        );
// useCallback dependency array
}, [sections]);

所以我不是在寻找与此问题相关的代码。如果可能的话,我正在寻找有关发生这种情况的详细说明。

我对为什么然后仅仅寻找答案或解决问题的正确方法感兴趣。

当在useEffect外部声明的useEffect依赖关系数组中传递函数时,为什么状态和prop均未更改,为什么会导致重新渲染。

2 个答案:

答案 0 :(得分:4)

问题在于,每个渲染周期都会重新定义markup。 React使用浅对象比较来确定值是否更新。每个渲染周期markup都有不同的参考。但是,您可以使用useCallback来记住该功能,以便引用稳定。您是否为短绒棉启用了react hook rules?如果这样做了,它可能会标记出来,告诉您原因,并提出解决参考问题的建议。

const markup = useCallback(
  (count) => {
    const stringCountCorrection = count + 1;
    return (
      // Some markup that references the sections prop
    );
  },
  [count, /* and any other dependencies the react linter suggests */]
);

// No infinite looping, markup reference is stable/memoized
useEffect(() => {
    if (sections.length) {
        const sectionsWithMarkup = sections.map((section, index)=> markup(index));
        setSectionBlocks(blocks => [...blocks, ...sectionsWithMarkup]);
    } else {
        setSectionBlocks(blocks => []);
    }
}, [sections, markup]);

答案 1 :(得分:0)

为什么在传递函数表达式时会创建无限循环

“无限循环”是指组件反复渲染,因为markup函数是每次组件渲染时useEffect是一个新的函数引用(内存中的指针),并且useCallback触发重新渲染。渲染,因为它是依赖项。

该解决方案就像@ drew-reese所指出的那样,使用markup钩子来定义您的library(vegan) #> Le chargement a nécessité le package : permute #> Le chargement a nécessité le package : lattice #> This is vegan 2.5-6 library(ggplot2) set.seed(2) community_matrix <- matrix( sample(1:100,300,replace=T),nrow=10, dimnames=list(paste("community",1:10,sep=""),paste("sp",1:30,sep=""))) example_NMDS <- metaMDS(community_matrix, # Our community-by-species matrix k=2, trace = 0) # The number of reduced dimensions data.scores <- as.data.frame(scores(example_NMDS)) data.scores$site <- rownames(data.scores) data.scores$grp <- rep(c("1", "2"), each = 5) species.scores <- as.data.frame(scores(example_NMDS, "species")) species.scores$species <- rownames(species.scores) ggplot() + geom_text(data=species.scores,aes(x=NMDS1,y=NMDS2,label=species), alpha=1) + # add the species labels geom_point(data=data.scores,aes(x=NMDS1,y=NMDS2,shape=as.factor(grp), colour=as.factor(site))) + # add the point markers geom_text(data=data.scores,aes(x=NMDS1,y=NMDS2,label=site, colour=as.factor(site)), vjust=0) + # add the site labels #scale_colour_manual(values=c("1" = "red", "2" = "blue")) + coord_equal() + theme_bw() 函数。