【问题标题】:React useEffect hook with warning react-hooks/exhaustive-deps反应 useEffect 带有警告的钩子 react-hooks/exhaustive-deps
【发布时间】:2020-02-21 07:03:42
【问题描述】:

我正在将使用 componentDidMount/Update/Unmount 生命周期的代码转换为 React Hooks,并在控制台中不断遇到 react-hooks/exhaustive-deps 作为警告。

我们的新代码似乎按预期工作,因此我的想法是关闭这些警告。但是,如果我遗漏了什么,下面的代码中是否需要警告。

componentDidMount/Update/Unmount代码

  state = {
    container: canUseDOM ? createContainer(this.props.zIndex) : undefined,
    portalIsMounted: false,
  };

  componentDidUpdate(prevProps: Props, prevState: State) {
    const { container } = this.state;
    const { zIndex } = this.props;
    if (container && prevProps.zIndex !== zIndex) {
      const newContainer = createContainer(zIndex);

      getPortalParent().replaceChild(container, newContainer);
      this.setState({ container: newContainer });
    } else if (!prevState.container && container) {
      getPortalParent().appendChild(container);
    }
  }

  componentDidMount() {
    const { container } = this.state;
    const { zIndex } = this.props;
    if (container) {
      getPortalParent().appendChild(container);
    } else {
      const newContainer = createContainer(zIndex);
      this.setState({ container: newContainer });
    }
    this.setState({
      portalIsMounted: true,
    });

    firePortalEvent(PORTAL_MOUNT_EVENT, Number(zIndex));
  }

  componentWillUnmount() {
    const { container } = this.state;
    const { zIndex } = this.props;
    if (container) {
      getPortalParent().removeChild(container);
      const portals = !!document.querySelector(
        'body > .portal-container > .portal',
      );
      if (!portals) {
        getBody().removeChild(getPortalParent());
      }
    }

    firePortalEvent(PORTAL_UNMOUNT_EVENT, Number(zIndex));
  }

新的 React Hooks 代码

const [container, setContainer] = useState(canUseDOM ? createContainer(zIndex) : undefined);
const [portalIsMounted, setPortalIsMounted] = useState(false);

  useEffect(() => {
    if (container) {
      const newContainer = createContainer(zIndex);
      getPortalParent().replaceWith(container, newContainer);
      setContainer(newContainer);
    }
  }, [zIndex]);

  useEffect(() => {
    if (container) {
      getPortalParent().appendChild(container);
    }
  }, [container]);

  useEffect(() => {
    if (container) {
      getPortalParent().appendChild(container);
    } else {
      const newContainer = createContainer(zIndex);
      setContainer(newContainer);
    }
    setPortalIsMounted(true);
    firePortalEvent(PORTAL_MOUNT_EVENT, Number(zIndex));
  }, []);

  useEffect(() => {
    if (container) {
      getPortalParent().removeChild(container);
      const portals = !!document.querySelector(
        'body > .portal-container > .portal'
      );
      if (!portals) {
        getBody().removeChild(getPortalParent());
      }
    }

    firePortalEvent(PORTAL_UNMOUNT_EVENT, Number(zIndex));
  }, []);

【问题讨论】:

  • componentWillUnmount 的代码应该从 useEffect 回调返回

标签: javascript reactjs react-hooks


【解决方案1】:

在这里,您在 useEffect 中使用容器,但是由于您也在此效果中设置容器状态,因此您不能将其作为依赖项,否则您将获得无限循环(每次调用 setContainer 时都会运行效果)。

我认为这可能是使用// eslint-disable-line 的可接受时间

useEffect(() => {       
   if (container) {
      const newContainer = createContainer(zIndex);
      getPortalParent().replaceWith(container, newContainer);
      setContainer(newContainer);
   }
// eslint-disable-line
}, [zIndex]);

可能还有其他示例,但您可以找出哪些 useEffects 需要哪些依赖项。

【讨论】:

  • 你能解释一下为什么这个错误实际上并没有发生吗?
  • 不确定我是否理解?
  • 对不起,我跳行了。我以为你声称 OP 有一个无限循环,因为我跳过了“否则”部分。
猜你喜欢
  • 2020-05-01
  • 2021-04-15
  • 2020-06-08
  • 2020-06-22
  • 2020-01-18
  • 2020-05-14
  • 2021-09-03
  • 1970-01-01
  • 2020-01-18
相关资源
最近更新 更多