无法从其他组件的功能主体内部更新组件

时间:2020-04-11 13:00:16

标签: javascript reactjs react-native react-hooks

在reactJS中,我想创建一个负责加载数据的函数。

此函数的调用在Controller(我组件的子代)中完成。

loadDataController更改时,我还想从state.perPage调用state.page函数。

我已经从类组件切换到功能组件,但错误仍然存​​在:

Cannot update a component from inside the function body of a different component

这是我的组件:

const MyPromotionsController = (props) => {
  const {
    children,
    fetchSuccess,
    t,
    loadingComponent: LoadingComponent,
    pagination: initialPagination,
    sort,
    filter,
    ...rest // eslint-disable-line no-unused-vars
  } = omit(props, [
    'setLocale',
    'locale',
  ]);
  const dataProvider = useDataProvider();
  const [pagination, setPagination] = useState(initialPagination);

  const _loadData = () => {
    const params = {
      pagination,
      sort,
      filter,
    };
    return dataProvider
      .getList('merchants/promotions', params);
  };

  return (
    <Controller
      pagination={pagination}
      FetchStart={LoadingComponent}
      FetchError={TranslatedFetchError}
      loadData={_loadData}
      onFetchSuccess={fetchSuccess}
      fetchStartMessages={{
        fetching: 'promotionsController.fetchStart.fetching',
      }}
      fetchErrorMessages={{
        error: 'promotionsController.fetchError.error',
      }}
    >
      {cloneElement(children, {
        pagination,
        setPagination,
      })}
    </Controller>
  );
};

我曾尝试像这样使用useEffect,但现在该函数从未被调用:

const MyPromotionsController = (props) => {
  const {
    children,
    fetchSuccess,
    t,
    loadingComponent: LoadingComponent,
    pagination: initialPagination,
    sort,
    filter,
    ...rest // eslint-disable-line no-unused-vars
  } = omit(props, [
    'setLocale',
    'locale',
  ]);
  const dataProvider = useDataProvider();
  const [pagination, setPagination] = useState(initialPagination);

  let _loadData = () => {};
  useEffect(() => {
    _loadData = () => {
      const params = {
        pagination,
        sort,
        filter,
      };
      return dataProvider
        .getList('merchants/promotions', params);
    };
  }, [pagination]);

  return (
    <Controller
      pagination={pagination}
      FetchStart={LoadingComponent}
      FetchError={TranslatedFetchError}
      loadData={_loadData}
      onFetchSuccess={fetchSuccess}
      fetchStartMessages={{
        fetching: 'promotionsController.fetchStart.fetching',
      }}
      fetchErrorMessages={{
        error: 'promotionsController.fetchError.error',
      }}
    >
      {cloneElement(children, {
        pagination,
        setPagination,
      })}
    </Controller>
  );
};

这是控制器:

class Controller extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: 0,
      data: null,
      error: null,
    };
  }

  async componentDidMount() {
    await this.refreshData();
  }

  async UNSAFE_componentWillReceiveProps(nextProps) {
    if (JSON.stringify(this.props.pagination) !== JSON.stringify(nextProps.pagination)) {
      console.log(nextProps);
      await this.refreshData();
    }
  }

  refreshData = async () => {
    const {
      loadData,
      onFetchStart,
      onFetchSuccess,
      onFetchError,
      fetchStart,
      fetchSuccess,
      fetchError,
      fetchErrorMessages: { error: errorMessage },
      t,
    } = this.props;
    this.setState({
      loading: 1,
    });
    try {
      fetchStart();
      if (onFetchStart) {
        onFetchStart();
      }
      const data = await loadData();
      this.setState({
        data,
        loading: 0,
        error: null,
      });
      fetchSuccess(data);
      if (onFetchSuccess) {
        onFetchSuccess(data);
      }
    } catch (e) {
      console.log(e);
      const error = new Error(t(errorMessage));
      fetchError(error);
      this.setState({
        data: null,
        loading: 0,
        error,
      });
      if (onFetchError) {
        onFetchError(new Error(t(errorMessage)));
      }
    }
  };

  render() {
    const {
      children,
      fetchStartMessages,
      fetchErrorMessages,
      FetchStart,
      FetchError,
      ...rest
    } = omit(this.props, [
      'onFetchSuccess',
      'onFetchStart',
      'onFetchError',
      'fetchSuccess',
      'fetchStart',
      'fetchError',
      't',
      'setLocale',
      'locale',
    ]);
    const { loading, data, error } = this.state;

    if (!error && !data && FetchStart) {
      return (
        <FetchStart
          messages={fetchStartMessages}
        />
      );
    }
    if (error && FetchError) {
      return (
        <FetchError
          loading={loading}
          error={error}
          onPress={this.refreshData}
          messages={fetchErrorMessages}
        />
      );
    }

    return cloneElement(children, {
      ...rest,
      data,
      error,
      loading,
      refreshData: this.refreshData,
    });
  }
}

如何解决这些警告?

0 个答案:

没有答案