2
\$\begingroup\$

My first go at a Higher Order Component in react.

Aims to give a component the ability to call an url repeatedly with a given refresh interval.

Seems to be working as I want. I'm not 100% confident that I'm using async/await correctly.

<MyComponent refresh={interval} url={`https://reqres.in/api/users?per_page=${count}`} />  

The HOC:

import React  from 'react'
import PropTypes from 'prop-types';

const apiCaller = () => WrappedComponent =>
    class extends React.Component {

        static propTypes = {
            url: PropTypes.string.isRequired,
            refresh: PropTypes.number.isRequired
        }

        static defaultProps = {
            url: '',
            refresh: 0
        }

        state = {
            error: null,
      data: null,
      loading: false
    }

      componentWillUnmount() {
            clearInterval(this.timer)
      }

        async componentDidMount() {
            try {

                // Call URL and wait for complete.
                await this.callApi(this.props.url)

                // Set up the refresh
                this.timer = setInterval(
                    () => this.callApi(this.props.url),
                    this.props.refresh * 1000
                )

            } catch (e) {
                this.setState({
                    loading: false,
                    error: e
                })
            }
        }

        async componentWillReceiveProps(nextProps) {
            try {
              if(this.props.url !== nextProps.url || this.props.refresh !== nextProps.refresh) {

                    // Get rid of the old timer.
                    clearInterval(this.timer)

                    // Call URL and wait for complete.
                    await this.callApi(nextProps.url)

                    // Set up the refresh again.
                    this.timer = setInterval(
                        () => this.callApi(nextProps.url),
                        nextProps.refresh * 1000
                    )
              }
            } catch (e) {
                this.setState({
                    loading: false,
                    error: e
                })
            }
        }

        async callApi(url){
            this.setState({
                loading: true
            })

            const response = await fetch(url)

            const json = await response.json()

            this.setState({
                data : json.data,
                loading: false
            })
        }

        render(){
            return <WrappedComponent {...this.state} {...this.props}  />
        }
    }

export { apiCaller }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.