简体   繁体   English

将数据获取组件包装在HOC中以在加载时显示微调器

[英]Wrap a data-fetching component in a HOC to show spinner while loading

I have a bunch of different react components that fetch data over api, they each have corresponding loadData action and isLoading reducer. 我有一堆不同的反应组件,通过api获取数据,它们每个都有相应的loadData动作和isLoading reducer。 I'm trying to write a HOC that will show loading spinner in place of component until data is loaded and component can be displayed. 我正在尝试编写一个HOC,它将显示加载微调器代替组件,直到加载数据并显示组件。

Right now isLoading is true -> spinner rendered -> isLoading becomes false -> child component rendered -> child's componentDidMount() executed -> this again calls loadData action that sets isLoading to false and so on and so on. 现在isLoading是真的 - > spinner呈现 - > isLoading变为false - >子组件呈现 - > child的componentDidMount()执行 - >这再次调用loadData动作,将isLoading设置为false等等。 How to prevent that and call loadData only once? 如何防止这种情况并仅调用loadData一次? Or maybe there's more elegant solution? 或者可能有更优雅的解决方案?

class DataList extends Component {
  componentDidMount() {
    this.props.loadData(); //action that pulls data via api
  }

  render() {
    return <p>{this.props.data}</p>;
  }
}

const withSpinner = (comp) => (props) => {
  if (props.isLoading) {
    return <p>Loading...</p>
  } else {
    return <comp {...props} />
  }
}

export default connect()(withSpinner(DataList));

// action that fetches data and updates state
const loadData = () => {
  setIsLoading(true);
  data = await fetchData();
  setIsLoading(false);
}

Well, one of the simplest ways you could fix this is by adding a dataLoaded value to wherever you're maintaining your state and set it to true when you've loaded your data. 好吧,您可以解决此问题的最简单方法之一是在您维护状态的位置添加dataLoaded值,并在加载数据时将其设置为true Then, just add a check before calling loadData and that will prevent additional load requests. 然后,只需在调用loadData之前添加一个检查,这将阻止其他加载请求。 It would look something like this: 它看起来像这样:

class DataList extends Component {
  componentDidMount() {
    if (!this.props.dataLoaded) { // call it whatever you want
      this.props.loadData(); //action that pulls data via api
    }
  }

  render() {
    return <p>{this.props.data}</p>;
  }
}

const withSpinner = (comp) => (props) => {
  if (props.isLoading) {
    return <p>Loading...</p>
  } else {
    return <comp {...props} />
  }
}

export default connect()(withSpinner(DataList));

// action that fetches data and updates state
const loadData = () => {
  setIsLoading(true);
  data = await fetchData();
  setIsLoading(false);
  setIsLoaded(true);
}

Alternatively, you could also put the dataLoaded inside of the loadData function if you have access to your state inside of that 或者,如果您可以访问其中的状态,也可以将dataLoaded放在loadData函数内

You have many options here. 你有很多选择。 Very simple solution would be to load data only if it is not present: 非常简单的解决方案是仅在不存在的情况下加载数据:

componentDidMount() {
  if (!this.props.data) {
     this.props.loadData();
  }
}

You can also introduce new flag into state which will be indicating whether data is loaded or not. 您还可以将新标志引入状态,该状态将指示是否加载数据。 Other solution would be to load data directly in HOC. 其他解决方案是直接在HOC中加载数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM