November 15, 2017
In one of our previous blogs, we mentioned how recompose improves both the readability and the maintainability of the code.
We also saw
how branch
and
renderComponent
functions
from recompose
help us
in deciding
which component to render
based on a condition.
We can use the code from renderComponent documentation to render a spinner component when the data is being fetched in a ReactJS application.
// PatientsList.js
import React, { Component } from 'react';
import LoadingIndicator from './LoadingIndicator';
export default class PatientsList extends Component {
state = {
isLoading: true,
patientsList: [],
}
componentDidMount() {
api.getPatientsList().then(responseData => {
this.setState({
patientsList: responseData,
isLoading: false,
})
})
}
render() {
const { isLoading } = this.state;
if (isLoading) {
return <LoadingIndicator isLoading={isLoading} />
} else {
return (
<ScrollView>
// Some header component
// View rendering the patients
</ScrollView>
)
}
}
In the above code,
when the PatientsList component mounts,
it fetches
the list of patients from the API.
During this time,
the isLoading
state is true
,
so we render
the LoadingIndicator
component.
Once the API call
returns with the response,
we set
the isLoading
state to false
.
This renders
ScrollView
component,
with our list of patients.
The above code works fine, but if our app has multiple screens, which show the loading indicator and fetch data, the above way of handling it becomes repetitive and hard to maintain.
Here's where Higher Order Components(HOC) are very useful. We can extract the logic for the ability to show the loading indicator in a HOC.
// withSpinner.js
import React from "react";
import { ScrollView } from "react-native";
import LoadingIndicator from "./LoadingIndicator";
const withSpinner = (Comp) => ({ isLoading, children, ...props }) => {
if (isLoading) {
return <LoadingIndicator isLoading={isLoading} />;
} else {
return <Comp {...props}>{children}</Comp>;
}
};
export default withSpinner;
Here,
we created a HOC component
which accepts a component
and the isLoading
prop.
If isLoading
is true,
we show the LoadingIndicator
.
If isLoading
is false,
we show the supplied component
with its children,
and pass in the props.
Now, we can use the above HOC in our PatientsList.js file. The supplied component can be any React Native component based on the use case. Here in our case, its a ScrollView.
// PatientsList.js
import { ScrollView } from 'react-native';
import withSpinner from './withSpinner';
const ScrollViewWithSpinner = withSpinner(ScrollView);
export default class PatientsList extends Component {
state = {
isLoading: true,
patientsList: [],
}
componentDidMount() {
api.getPatientsList().then(responseData => {
this.setState({
patientsList: responseData,
isLoading: false,
})
})
}
render() {
const { isLoading } = this.state;
return(
<ScrollViewWithSpinner
isLoading={isLoading}
// other props
>
// Some header component
// View rendering the patients
</ScrollViewWithSpinner>
)
}
Because of the above extraction of logic to a HOC, we can now use the same HOC in all our components which render a loading indicator while the data is being fetched.
The logic to show a loading indicator now resides in a HOC. This makes the code easier to maintain and less repetitive.
If this blog was helpful, check out our full blog archive.