2019-06-27
|~3 min read
|531 words
If I’m working on a React application that is trying to render data based on an asynchronous call, there are three common cases I should handle:
There are plenty of ways to structure a React component, but one pattern that my team showed me recently, I really liked for the readability it provided.
A generic look at the pattern I found appealing is:
import {ErrorComponent, Loader} from 'shared/components'
import Header from './components/header'
import Footer from './components/footer'
import DataComponent from './component/datacomponent'
function MyComponent() {
const fetchResults = useAsync( () => API.getResults()
const ComponentWrapper = children => (
<div className={"my-component-style"}>
<Header />
{children}
<Footer />
</div>
);
if (fetchResults.loading) return ComponentWrapper(loader);
if (fetchResults.error || !fetchResults.value) return ComponentWrapper(error);
return ComponentWrapper(<DataComponent data={fetchResults.value} />);
};
ErrorComponent
and Loader
component from a shared directory — these can be anything, but the point is that it’s likely the case that if I adopt this pattern, I’ll use them multiple times across a project. In this case, I’m assuming they are JSX ElementsuseAsync
from react-use
. The method returns an object with three keys: value
, error
, and loading
.Header
and Footer
component that will be shared among all of the states and is applied through the wrapper.What I like about this is how easy it is to understand what’s happening and the absence of any if / else blocks or ternary logic in the return block. While it does “violate” the Single Return Statement law, this feels to me like an appropriate early escape.
That was actually my approach before I’d found this pattern, and while it works, it doesn’t make it any easier for the next person coming along to understand what’s going on — and arguably, it’s much more difficult.
return fetchResults.loading
? ComponentWrapper(loader)
: fetchResults.error || !fetchResults.value
? ComponentWrapper(error)
: ComponentWrapper(<DataComponent data={fetchResults.value} />)
As with all rules, there are good reasons to listen and adhere to them. Knowing when it doesn’t make sense, however, is critical for moving to the next level. The only way to learn is to have an open mind and not hold any position as dogmatic.
Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!