【问题标题】:Higher-Order Component Being Called Multiple Times高阶组件被多次调用
【发布时间】:2017-07-10 09:13:05
【问题描述】:

我创建了以下高阶组件:

const baseComponent = (WrappedComponent: React.ComponentClass<any>) => (props: IKeyValue) => {
  if (props.isLoading) {
    return (
      <LoadingSpinnerComponent shown={true} />
    );
  }

  return (
    <WrappedComponent {...props} />
  );
};

这导致该组件被无限期地调用。 (myComponent 中的componentDidMount 意味着正在重新创建此组件。

我的使用方式如下:

export default connect(
  mapStateToProps,
  dispatchToProps,
)(baseComponent(myComponent)) as React.ComponentClass<any>;

删除 if 部分时:

  if (props.isLoading) {
    return (
      <LoadingSpinnerComponent shown={true} />
    );
  }

组件只会被调用一次。 我试图深入调试 react lib 代码,但魔法对我来说是一个奇迹。有什么想法吗?

提前致谢!

编辑:

完整代码: myComponent:

class MiniCatalogContainer extends React.PureComponent<IProps, void> {
  public componentDidMount() {
    const { fetchCatalog} = this.props;
    fetchCatalog({path});
  }

  public render() {
    ...
  }
}

export default connect(
  mapStateToProps,
  dispatchToProps,
)(baseComponent(MyComponent)) as React.ComponentClass<any>;

promise-middleware

import { Dispatch } from 'react-portal/src/interfaces';
import isPromise from 'react-portal/src/utils/is-promise';

interface IOptions {
  dispatch: Dispatch;
}

export default function promiseMiddleware({ dispatch }: IOptions) {
  return (next: Dispatch) => (action: any) => {
    if (!isPromise(action.payload)) {
      return next(action);
    }

    const { types, payload, meta } = action;
    const { promise, data } = payload;
    const [ PENDING, FULFILLED, REJECTED ] = types;

   /**
    * Dispatch the pending action
    */
    dispatch( { type: PENDING,
                ...(data ? { payload: data } : {}),
                ...(meta ? { meta } : {}),
    });

    /**
     * If successful, dispatch the fulfilled action, otherwise dispatch
     * rejected action.
     */
    return promise.then(
      (result: any) => {
        dispatch({
          meta,
          payload: result,
          type: FULFILLED,
        });
      },
      (error: any) => {
        dispatch({
          meta,
          payload: error,
          type: REJECTED,
        });
      },
    );
  };
}

解决方案:

正如@Shleng 所注意到的,循环是因为我在组件内部调用了fetch。我最终得到了简单的解决方案:

const baseComponent = (WrappedComponent: React.ComponentClass<any>) => (props: IKeyValue) => {
      if (props.isLoading) {
        return (
          <LoadingSpinnerComponent shown={true} />
          <WrappedComponent {...props} />
        );
      }

      return (
        <WrappedComponent {...props} />
      );
    };

【问题讨论】:

  • 您是否正在调度一些将更改 myComponent 的 componentDidMount 中的 isLoading 的操作?
  • 您的props.isLoading 属性在初始化后似乎没有得到稳定的值。追踪其价值可能会有所帮助。
  • 你能给我们看看mapStateToProps。如何通知所有组件它们是否正在加载?你有 componentType.loading 状态键还是它们都依赖于状态的变化来确定 mapStateToProps 传递的加载属性
  • @Sheng 是的!但一组是isLoading=true,下一组是假的。就是这样。

标签: reactjs redux react-redux higher-order-components


【解决方案1】:

因为您在包装组件的componentDidMount 内调用了fetchCatalog,所以工作流会导致如下所示的循环:

mount WrappedComponent -> fetch -> mount Spinner -> loaded -> mount WrappedComponent -> fetch (loop!)

isLoading: false       -> true                   -> false                            -> true

【讨论】:

  • 确实,我没有看到。谢谢!
猜你喜欢
  • 2020-03-08
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 2017-09-05
  • 2021-09-16
  • 2018-12-30
  • 1970-01-01
相关资源
最近更新 更多