After the emergence of React Hooks, is Render props still useful

Keywords: Front-end React

render props is a very popular development mode for logical reuse between components. Since the emergence of React 16.8 Customize Hook Is render props NO longer needed after it is used for logical reuse between components? The answer is NO! Render props is still useful for building reusable components

What is render prop

A render prop is a function type component property (prop). The return value of this function is used to render something, such as rendering a JSX

interface Props {
  ...
  renderItem?: (item: string) => JSX.Element;
  renderHeader?: () => JSX.Element;
}
Copy code

This allows the user of the component to decide what needs to be rendered at a specific location. This makes components very flexible and highly reusable.

Each component has a render prop

Each component has one children attribute

export const Card: FC = ({ children }) => (
  <div className="card">{children}</div>
);
Copy code

Children is a render prop. In the above example, the children attribute allows the user of the component to render customized content. For example:

<Card>
  <p>Some interesting text</p>
  <button>Click me</button>
</Card>
Copy code

Create render prop

Let's create our own render prop

interface Props {
  title?: string;
  renderHeader?: () => JSX.Element;
}
export const Card: FC<Props> = ({ children, title, renderHeader }) => (
  <div className="card">
    <div className="card-header">
      {renderHeader ? renderHeader() : title !== undefined ? title : null}
    </div>
    <div className="card-content">{children}</div>
  </div>
);
Copy code

Our Card component has a header. Users can use renderHeader to override the default display effect of the header

Let's see how to use the Card component

<Card renderHeader={() => <h3>A custom header</h3>}>
  <p>Some interesting text</p>
  <button>Click me</button>
</Card>
Copy code

The above is an example of using the renderHeader attribute in the Card component to customize the rendering head effect. The renderHeader attribute is an arrow function and returns the content of a h3 label package

Now, let's begin to understand the role of render props and how to make it super flexible and reusable in components.

Create a list component that can be reused

interface Props {
  data: string[];
  renderItem?: (item: string) => JSX.Element;
  renderHeader?: () => JSX.Element;
}
export const List: FC<Props> = ({ data, renderItem, renderHeader }) => (
  <div className="list">
    <div className="list-header">{renderHeader && renderHeader()}</div>
    <ul>
      {data.map((item) => (
        <li key={item}>{renderItem ? renderItem(item) : item}</li>
      ))}
    </ul>
  </div>
);
Copy code

The above is a simple List component, which has two render prop renderItem and renderHeader. Note that renderItem has a parameter, which is used to display on the interface

<List
  data={["Fred", "Bob", "Jane"]}
  renderHeader={() => <h3>Names</h3>}
  renderItem={(item) => (
    <div>
      <span style={{ marginRight: "10px" }}>{item}</span>
      <button>Click me</button>
    </div>
  )}
/>
Copy code

An example of using the List component in the last interview,

  • Use the renderHeader property as an arrow function and h3 wrap the contents of the
  • Use the renderItem property to return each item of the list together with a button component as the rendering result of each row of data

summary

  • render props is still very useful when component users need to render custom group elements in highly reusable components

  • Each React component will have a render prop- children to allow users to render custom elements at a certain location of the component.

  • We can create our own render props in the component to allow users to render custom elements in multiple different locations of the component.

  • render props accepts parameters that are useful when rendering a list of data items using render prop.

Reference documents: Render props are still useful | Building SPAs

Posted by yacahuma on Sat, 27 Nov 2021 20:19:05 -0800