如何修复警告“函数——使 useEffect Hook 的依赖关系在每次渲染时发生变化”?

wef*_*wef 5 javascript reactjs react-hooks

如何修复警告 'createGraphics' 函数会使 useEffect Hook(第 77 行)的依赖项在每次渲染时发生变化。将其移动到 useEffect 回调中。或者,将“createGraphics”定义包装到它自己的 useCallback() 钩子中。

而且,当我尝试创建空依赖项数组时,我会收到此警告 - React Hook React.useEffect 缺少依赖项:'createGraphics'。包括它或删除依赖项数组

import React from "react";
import * as d3 from "d3";
import { GraphicsItem, StatsWrapper } from "../style";
import "../assets/style.css";

export const GraphicItem = ({ graphNames, screenSize }) => {
  const createGraphics = () => {
    let randArray = function () {
      for (var i = 0, array = new Array([]); i < 19; i++) {
        array.push(Math.floor(Math.random() * 19 + 1));
      }
      return array;
    };
    let initRandArray = randArray();

    let w = screenSize >= 1920 ? 220 : 150;
    let h = 130;
    let barPadding = 1;
    let mAx = d3.max(initRandArray);
    let yScale = d3.scaleLinear().domain([0, mAx]).range([0, h]);

    let svg1;

    svg1 = d3.select(`.item0`).append("svg").attr("width", w).attr("height", h);

    function setSvgItem(svg) {
      svg
        .selectAll("rect")
        .data(initRandArray)
        .enter()
        .append("rect")
        .attr("x", function (d, i) {
          return i === 18
            ? screenSize >= 1920
              ? "61"
              : "41.5"
            : i === 19
            ? screenSize >= 1920
              ? "136"
              : "93"
            : i * (w / initRandArray.length);
        })
        .attr("y", function (d) {
          return h - yScale(d);
        })
        .attr("width", w / initRandArray.length - barPadding)
        .attr("height", function (d) {
          return yScale(d);
        })
        .attr("fill", function (d, index) {
          return index === 19
            ? "rgb(246 185 46)"
            : index === 18
            ? "rgb(0 212 198)"
            : "rgb(rgb 16 19 " + d * 100 + ")";
        });
    }

    const setSvgElements = () => {
      setSvgItem(svg1);
    };

    return setSvgElements();
  };

  React.useEffect(() => {
    createGraphics();
  }, [createGraphics]);

  return (
    <>
    ///////
    </>
  );
};

Run Code Online (Sandbox Code Playgroud)

sec*_*can 15

我认为您不需要添加createGraphicsuseEffect()依赖项数组中,但是如果必须的话,您可以将该函数包装在一个useCallback()钩子中:

export const GraphicItem = ({ graphNames, screenSize }) => {
  const createGraphics = React.useCallback(() => { 
    /* function body */ 
  }, [screenSize]);

  React.useEffect(() => {
    createGraphics();
  }, [createGraphics]);

  return (
    <>
    ///////
    </>
  );
};
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是createGraphics在组件外部声明,这样组件每次重新渲染时就不会重新实例化。在这种情况下,您必须稍微修改该函数,以便它接受一个参数 ( screenSize),当您在挂钩中调用该函数时,该参数将传递给它useEffect

function createGraphics(screenSize) {
    /* function body */
}

export const GraphicItem = ({ graphNames, screenSize }) => {
  React.useEffect(() => {
    createGraphics(screenSize);
  }, [screenSize]);

  return (
    <>
    ///////
    </>
  );
};
Run Code Online (Sandbox Code Playgroud)


Ash*_*Lim 8

React 正在抱怨,因为createGraphics是在组件的主体中定义的。这意味着每次重新渲染组件时,createGraphics都会将其重新创建为新的函数引用。

请注意您如何在?中指定createGraphics为依赖项。useEffect该依赖数组用于记忆。你是说“嘿,React,只有在createGraphics发生变化时才会产生这种效果”。但由于上述原因,它正在改变每个渲染,因此发出警告。

所以你可以通过这样做来解决这个问题:

React.useEffect(() => {
    const createGraphics = () => {
        // your function using screenSize here
    }

    createGraphics();
  }, [screenSize]);
Run Code Online (Sandbox Code Playgroud)

或者

const createGraphics = React.useCallback(() => {
    // your function using screenSize here
  }, [screenSize]);

// use createGraphics elsewhere
Run Code Online (Sandbox Code Playgroud)

这样,只有更改screenSize才会创建新createGraphics功能。

关于“React Hook React.useEffect 缺少依赖项:'createGraphics'”,这是警告您空的依赖项列表意味着createGraphics即使发生更改也永远不会更新screenSize。换句话说,将始终引用挂载的组件createGraphics的第一个实例。screenSize