React Render Props 怎么用?怎么在组件间共享状态?

文章导读
Previous Quiz Next 由于 React 组件通过组合(一个组件包含在另一个组件内)而非继承来互联,因此 React 组件中的逻辑不会直接共享给另一个组件。React 提供了多种在组件间共享逻辑的方式,其中一种是 Render props。Render prop
📋 目录
  1. 如何使用 render props
  2. 应用 render props
A A

React - Render Props



Previous
Quiz
Next

由于 React 组件通过组合(一个组件包含在另一个组件内)而非继承来互联,因此 React 组件中的逻辑不会直接共享给另一个组件。React 提供了多种在组件间共享逻辑的方式,其中一种是 Render props。Render props 本质上是将带有必要渲染逻辑的函数通过 props 传递给具有核心功能的组件,因此被称为 render props。

在本章中,我们将学习如何使用 render props。

如何使用 render props

让我们逐步了解如何使用 render props 并在两个组件间共享逻辑。考虑从外部 URL 获取并渲染数据的场景。

  • 创建一个组件 FetcherComponent,用于从外部 URL 获取数据,以及 FetcherConsumerComponent,用于消费数据并渲染。

  • 创建一个组件 FetcherComponent,包含给定 URL(props.url)的数据获取逻辑。

componentDidMount() {
   fetch(this.props.url)
   .then((response) => response.json())
   .then((data) => {
      this.setState({
         data: data
      });
   });
}

现在,更新 FetcherComponent,使其将核心渲染逻辑委托给 props(this.props.render)。

render() {
   return (
      <div>
         <h2>Fetch react component</h2>
         {this.state.data && this.props.render(this.state.data)}
      </div>
   )
}

这里,

  • this.props.render 是带有渲染逻辑的函数,由其他组件通过 props 传递给 FetcherComponent。

  • 创建一个组件 FetcherConsumerComponent,并通过传递获取数据的渲染逻辑来渲染 FetcherComponent。

render() {
   return (<FetcherComponent url="users.json" render={(items) => (
      <ul>
         {items && items.length && items.map((item) =>
            <li key={item.id}>{item.name}</li>
         )}
      </ul>
   )} />)
}

这里,

  • items 是由 FetcherComponent 获取的数据。

  • 这些数据被循环遍历并生成 HTML 无序列表。

我们可以按照本节所述步骤创建工作示例,详见下一节。

应用 render props

首先,创建一个新的 React 应用,并使用以下命令启动它。

create-react-app myapp
cd myapp
npm start

接下来,打开 App.css (src/App.css) 并删除所有 CSS 类。

FetchRenderProps.js

然后,创建一个组件 FetchRenderProps (src/components/FetchRenderProps.js),包含以下数据获取逻辑 −

import React from "react";
class FetchRenderProps extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         data: []
      }
   }
   componentDidMount() {
      fetch(this.props.url)
      .then((response) => response.json())
      .then((data) => {
         console.log(data)
         this.setState({
            data: data
         });
      });
   }
   render() {
      return (
         <div>
            <h2>Fetch react component</h2>
            {this.state.data && this.props.render(this.state.data)}
         </div>
      )
   }
}
export default FetchRenderProps;

这里我们有,

  • componentDidMount 事件中使用 fetch JavaScript 方法从外部 URL 获取数据。

  • 使用通过 props 传递的 render 方法渲染获取到的数据。

users.json

接下来,在 public 文件夹中创建一个文件 users.json (public/users.json) 来存储用户信息。我们将尝试使用 FetchRenderProps 组件获取它并在应用中显示。

[{"id":1,"name":"Fowler","age":18},
{"id":2,"name":"Donnell","age":24},
{"id":3,"name":"Pall","age":26}]

todo_list.json

接下来,在 public 文件夹中创建一个文件 todo_list.json (public/todo_list.json) 来存储 todo list 信息。我们将尝试使用 FetchRenderProps 组件获取它并在应用中显示。

[{"id":1,"title":"Learn JavaScript","is_done":true},
{"id":2,"title":"Learn React","is_done":true},
{"id":3,"title":"Learn Typescript","is_done":false

SimpleRenderProps.js

接下来,创建一个组件 SimpleRenderProps (src/components/SimpleRenderProps.js) 来使用 FetchRenderProps 组件,如下所示 −

import React from "react";
import FetchRenderProps from "./FetchRenderProps";
class SimpleRenderProps extends React.Component {
   render() {
      return (
         <>
            <FetchRenderProps url="users.json" render={(items) => (
               <ul>
                  {items && items.length && items.map((item) =>
                     <li key={item.id}>{item.name}</li>
                  )}
               </ul>
            )} />
            <FetchRenderProps url="todo_list.json" render={(items) => (
               <ul>
                  {items && items.length && items.map((item) =>
                     <li key={item.id}>{item.title} {item.is_done && <strong>Done</strong>}</li>
                  )}
               </ul>
            )} />
         </>
      )
   }
}
export default SimpleRenderProps;

这里我们有,

  • 使用 FetchRenderProps 与 users.json 获取并渲染用户列表

  • 使用 FetchRenderPropstodo_list.json 获取并渲染 todo 列表

  • 获取用户和 todo 列表都使用相同的 FetchRenderProps 组件。

App.js

接下来,打开 App.js 文件并渲染 SimpleRenderProps 组件,如下所示 −

import './App.css'
import React from 'react';
import SimpleRenderProps from './components/SimpleRenderProps'
function App() {
   return (
      <div className="container">
         <div style={{ padding: "10px" }}>
            <div>
               <SimpleRenderProps />
            </div>
         </div>
      </div>
   );
}
export default App;

最后,在浏览器中打开应用并检查最终结果。应用将如下所示渲染 −

Applying Render Props

总结

Render props 是一种在组件之间共享逻辑的高效方法。它在许多第三方组件中被广泛使用,具有良好的成功率,并且是 React 领域中经过时间考验的共享逻辑方法。