React useEffect hook с предупреждающими реакционными крючками / исчерпывающим падением - PullRequest
1 голос
/ 25 октября 2019

Я конвертирую код, который использовал 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));
  }, []);

1 Ответ

1 голос
/ 25 октября 2019

Здесь вы используете контейнер в своем useEffect, однако, поскольку вы также устанавливаете состояние контейнера в этом эффекте, вы не можете поместить его в качестве зависимости, иначе вы получите бесконечный цикл (эффект будет выполняться каждый раз, когда вызывается setContainer).

Я думаю, что это может быть приемлемое время для использования // eslint-disable-line

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

Могут быть и другие примеры, но вы можете выяснить, какие useEffects требуют каких зависимостей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...