【问题标题】:Creating a React higher order component, to serve as a "loader"(animation) wrapper for child components创建一个 React 高阶组件,作为子组件的“加载器”(动画)包装器
【发布时间】:2018-04-26 21:45:34
【问题描述】:

我有很多组件,需要在 componentDidMount 方法中发送一些 ajax 函数。我想创建一个 HOC,其唯一目的是向组件“应用”一些动画,并在解决某个承诺后停止该动画。

当然,我可以为每个组件复制粘贴此代码,但我想创建一些处理它的抽象。

问题是,我不知道如何正确地将函数从孩子传递给父母。例如,我们假设预期的子组件有这个 componentDidMount:

componentDidMount() {
ajax('/costumers')
  .then(({ data }) => {
    this.setState(() => ({ costumers: data.content }))
  })
}

从技术上讲,我需要将此函数作为参数传递给 HOC,或者可能以某种方式“劫持”孩子的 componentDidMount(如果有可能的话......)。 HOC 会在加载后应用动画,然后发送 ajax,只有当它被解决时,动画才会被消除,子组件才会被渲染。

如何做到这一点?

任何想法将不胜感激

【问题讨论】:

  • 这听起来你需要调查github.com/reactjs/react-redux
  • 我对 Redux 相当熟悉。你能给我一些具体的方向吗?我从来没有将 Redux 用于此类目的。它总是用于获取一些将被全局使用的数据,例如身份验证状态
  • redux.js.org/advanced/async-actions 我想这就是你所追求的
  • 我以前使用 Thunk 进行异步 Redux 操作,但我不明白操作如何帮助我用功能“包装”我的组件。我在这里错过了什么吗?
  • 将 ajax 调用与子组件的 mount 函数分开并将其放在...其他任何地方。在 ajax 调用开始时,将操作推送到状态(ajax 调用开始),错误时推送错误状态,成功时推送已完成状态和数据。让组件对这些状态做出反应,而不是管理它们

标签: javascript reactjs higher-order-components


【解决方案1】:

以下是针对这种情况编写 HOC 的方法,有关该主题的更多信息,请参阅 React docs

const withLoader = (loader, Component) =>
  class WithLoader extends React.Component {
    state = { ready: false, data: null };

    async componentDidMount() {
      const data = await loader();

      this.setState({ ready: true, data });
    }

    render() {
      if (!this.state.ready) return <div>LOADING</div>; // or <ComponentWithAnimation />

      return <Component data={this.state.data} />;
    }
  };

const Test = props => <div>DATA: {props.data}</div>;

const fakeLoader = () =>
  new Promise(res => setTimeout(() => res("My data"), 1000));

const TestWithLoader = withLoader(fakeLoader, Test);

【讨论】:

  • 这太棒了,谢谢!这里唯一需要注意的是,它要求我为 HOC 提供一个返回承诺的“外部”函数。我不能只为它提供一个子类的方法(在你的例子中,函数是“fakeloader”)。你认为有什么方法可以从子类中向 HOC 传递一个函数吗?
  • 有没有办法“劫持”子组件的 componentDidMount 方法?
  • 使用 hoc 的整个想法是,它允许您取出所有逻辑,然后您只需使用该 hoc 智能的虚拟组件。如果你不能取出负责加载数据的逻辑,那么你需要的不是 hoc。为什么不能更新逻辑?
  • 请注意,如果您正在发出网络请求,您应该已经在使用 Promise,只需将该请求带到外部并更改它以返回数据,而不是直接将其注入其组件状态。
  • const actualLoader = ajax('/foo').then(({ data }) =&gt; data.content);,但现在有了 hoc,您使用 this.props.data 而不是 this.state.customers。您还可以将 hoc 更新为具有动态属性名称,这意味着它可以根据需要提供 this.props.customers
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-07
  • 2019-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多