Using the Render Props Pattern in React: Building a Flexible Fetcher Component
Article Image Bg

When building React applications, one common task is fetching data from an API and displaying it. The render props pattern provides a powerful way to create flexible, reusable components for data fetching. In this post, we’ll explore how to build a `Fetcher` component using the render props pattern.

What is the Render Props Pattern?

The render props pattern is a technique for sharing code between components in React. It involves passing a function as a prop to a component, which then uses that function to determine what to render. This allows for greater flexibility and re-usability in your components.

Building the Fetcher Component

Let’s dive into the implementation of a `Fetcher` component that uses the render props pattern.

Component Code

import React, { useEffect, useState } from "react"; import axios from "api/axios"; interface Response {  loading: boolean;  json: Record<string, any> | Array<Record<string, any>>; } const RESPONSE_PARAMS: Response = {  loading: false,  json: [] || {}, }; interface Props {  api: string;  render: Function;  enableSearch?: boolean;  searchTerm?: string;  loadingLabel?: boolean | string;  defaultParams?: { [key: string]: string | number }; } const Fetcher: React.FC<Props> = ({  api,  render,  defaultParams,  loadingLabel,  searchTerm = "", }) => {  const [response, setResponse] = useState<Response>(RESPONSE_PARAMS);  useEffect(() => {    fetchData(defaultParams).catch((err) => console.error(err));  }, [searchTerm]);  const fetchData = async (defaultParams: any) => {    setResponse((prevState) => ({      ...prevState,      loading: true,    }));    const resp = await axios.get(api, { params: defaultParams });    const response = resp.data.data;    setResponse((prevState) => ({      ...prevState,      loading: false,      json: response,    }));  };  if (loadingLabel && response.loading)    return (      <span>        Loading {typeof loadingLabel == "boolean" ? "" : loadingLabel}...      </span>    );  return <div>{render(response)}</div>; }; export default Fetcher;

How It Works

1. Props and State

The Fetcher component accepts several props including api (the API endpoint), render (a function to render the fetched data), and optional props like defaultParamsloadingLabel, and searchTerm.

The component manages the response state which includes loading (a boolean) and json (the fetched data).

2. Fetching Data

The fetchData function makes an HTTP GET request to the provided api endpoint using axios. It updates the response state to indicate loading and then to store the fetched data.
The useEffect hook triggers fetchData whenever searchTerm changes.

3. Conditional Rendering

If loadingLabel is provided and the data is still loading, a loading message is displayed.
Otherwise, the render function is called with the response state to display the fetched data.

Using the Fetcher Component

Here’s an example of how to use the Fetcher component:

import React from "react"; import Fetcher from "./Fetcher"; const App = () => {   return (     <Fetcher       api="https://api.example.com/data"       render={(response) => (         <div>           {response.loading ? (             <p>Loading…</p>             ) : (               <pre>{JSON.stringify(response.json, null, 2)}</pre>               )}           </div>         )}       />     ); }; export default App;

In this example:

The render prop is a function that takes the response state as an argument.
It conditionally renders a loading message or the fetched JSON data.

Benefits of Using Render Props

The render props pattern offers several advantages:

Flexibility: The parent component has full control over the rendering logic.
Reusability: The Fetcher component can be reused across different parts of the application, fetching data from various APIs and rendering it in different ways.
Separation of Concerns: The fetching logic is encapsulated within the Fetcher component, while the rendering logic is handled by the parent component.

Conclusion

The render props pattern is a powerful tool in React that enables you to create flexible and reusable components. By using this pattern in the Fetcher component, we can efficiently handle data fetching and rendering, making our code more maintainable and scalable.

Give it a try in your next project and experience the benefits of this pattern firsthand!