React js教程(14):在 ReactJS 中渲染属性(Render Props)和上下文(Content)

作者 : 慕源网 本文共6280个字,预计阅读时间需要16分钟 发布时间: 2021-10-27 共336人阅读

本文是React 教程系列的一部分。您可以在此处找到本系列之前所有帖子的链接

介绍

上一篇文章中,我们了解了 React 中的高阶组件及其用法。在本文中,我们将介绍 Render Props 和 React 中 Context 的概念。

Render Props

React 中的 Render Props 是为组件的 props 分配一个函数并在组件的 render 方法中调用的东西。调用该函数将返回一个 React 元素或组件。React Router 和 Downshift 等第三方库使用这种方法。

render prop是组件用来知道要渲染什么的函数属性。通过这个,我们还可以将一个状态传递给另一个状态。

让我们看一个演示。

创建一个 Movement.js 文件和代码如下,

import React, { Component } from 'react'  
  
export class Movement extends Component {  
  
    constructor(props) {  
        super(props)  
      
        this.state = {  
                x:0,  
                y:0  
        }  
    }  
      
    onMouseMove =(event) => {  
        this.setState({  
            x:event.clientX,  
            y:event.clientY  
        })  
    }  
  
    render() {  
        const{x,y} = this.state  
        return (  
            <div style={{height : '100%'}} onMouseMove={this.onMouseMove}>  
                <h1> The current mouse position is ({x},{y})</h1>  
            </div>  
        )  
    }  
}  
  
export default Movement

现在在 App.js 中添加这个 Movement.js,

import React from 'react';  
import './App.css';  
import './css/custom.css';  
import Movement from './components/Movement'  
  
function App() {  
  return (      
    <div>  
      <Movement></Movement>  
    </div>  
  );  
}  
  
export default App;  

上面的代码将显示如下输出。

现在让我们继续演示,我们将创建一个名为 Monkey 的组件,在其中移动鼠标时,猴子也会跟随香蕉移动。

让我们看看演示。修改Movement.js的代码如下。

import React, { Component } from 'react'  
import PropTypes from 'prop-types'  
  
export class Movement extends Component {  
  
    static propTypes = {  
        render: PropTypes.func.isRequired  
    }  
  
    state={x:0,y:0}    
      
    onMouseMove =(event) => {  
        this.setState({  
            x:event.clientX,  
            y:event.clientY  
        })  
    }  
  
    render() {          
        return (  
            <div onMouseMove={this.onMouseMove}>  
               {this.props.render(this.state)}  
            </div>  
        )  
    }  
}  
  
export default Movement
现在,使用以下代码创建 Monkey.js。对于下面,我们还需要分别在Demo2的源代码中上传的2张猴子和香蕉的图像。
import React, { Component } from 'react'  
import monkey from '../images/monkey.jpg'  
import banana from '../images/banana.jpg'  
  
export class Monkey extends Component {  
    render() {  
        const{x,y} = this.props.Movement  
  
        return (  
            <div>  
                <img src={monkey} alt='monkey' style={{position:'relative',left:x,right:y,height:150}}></img>                      
                <img src={banana} alt='banana' style={{position:'relative',left:(x+10),right:(y+10),height:30}}></img>                      
            </div>  
        )  
    }  
}  
  
export default Monkey 
现在,在最后一步,在 App.js 中调用 Monkey.js。
import React from 'react';  
import './App.css';  
import './css/custom.css';  
import Movement from './components/Movement'  
import Monkey from './components/Monkey'  
  
function App() {  
  return (      
    <div>           
      <Movement render={({x,y}) =>  (  
        <Monkey Movement={{x,y}}/>  
      )}/>  
  
    </div>  
  );  
}  
  
export default App;  

这将显示如下输出。

在上图中,移动鼠标时,猴子也会移动。上面的演示非常有趣,让我们允许使用 react-motion API 创建其他动画。

现在,我们将看到 ReactJS 中 Context 的概念。

Context

React.js 中的上下文是通过组件树传递数据的概念,而无需手动将 props 向下传递到每个级别。

在基本的 React 应用程序中,将数据从父级传递到子级是使用 props 完成的,但是如果数据需要在多个级别上传递,例如传递应用程序中大多数组件所需的用户名或主题,这是一种繁重的方法。Context 允许您提供在组件之间共享值的功能,而无需通过组件树的每一层显式传递 props。

当不需要传递道具时需要将当前身份验证、主题或首选语言传递给子级别时,主要使用上下文。

要使用上下文获取数据,我们需要遵循 3 个步骤,

  1. 我们需要首先创建上下文。
  2. 然后我们需要为上下文提供价值。
  3. 最后,我们需要消耗上下文的值。

现在让我们看一下演示,

例如 – 在当前演示中,我们将看到如何使用上下文在子组件中使用用户名。

首先,我们将创建一个新文件 UserContext.js。这是我们创建上下文的第一步

import React from 'react'  
  
const UserContext = React.createContext()  
  
const UserProvider = UserContext.Provider  
  
const UserConsumer = UserContext.Consumer  
  
export {UserProvider,UserConsumer}  

现在,我们将创建一个嵌套结构,我将在其中创建 3 级组件主组件 -> 主页组件 -> 配置文件组件。

我们将在 App.js 中执行我们需要为消费者提供价值的第二步,

import React from 'react';  
import './App.css';  
import './css/custom.css';  
import MasterComponent from './components/MasterComponent'  
import { UserProvider } from './components/UserContext';  
  
function App() {  
  return (  
    <div className="App">  
      <UserProvider value="New User">  
        <MasterComponent />  
      </UserProvider>  
    </div>  
  );  
}  
  
export default App;  
MasterComponent.js 
import React, { Component } from 'react'  
import HomeComponent from './HomeComponent'  
class MasterComponent extends Component {  
    render() {  
        return (  
            <div>  
                <HomeComponent/>  
            </div>  
        )  
    }  
}  
  
export default MasterComponent
现在二级组件被命名为 HomeComponent.js
import React, { Component } from 'react'  
import ProfileComponent from './ProfileComponent'  
  
class HomeComponent extends Component {  
    render() {  
        return (  
            <div>  
                <ProfileComponent/>  
            </div>  
        )  
    }  
}  
  
export default HomeComponent  
第三级组件名为 ProfileComponent,我们将在其中使用上下文值
import React, { Component } from 'react'  
import { UserConsumer } from './UserContext';  
  
class ProfileComponent extends Component {  
    render() {  
        return (  
           <UserConsumer>  
               {  
                   (username) => {  
                       return <div>Hello {username}</div>  
                   }  
               }  
           </UserConsumer>  
        )  
    }  
}  
  
export default ProfileComponent  

现在输出将显示如下,

如果在 UserContext.js 中创建上下文时我们将定义默认值,如果我们不在组件中提供任何值,那么它将从 UserContext 中获取默认值,

import React from 'react'      
const UserContext = React.createContext('Guest')      
const UserProvider = UserContext.Provider      
const UserConsumer = UserContext.Consumer      
export {UserProvider,UserConsumer} 
App.js 代码如下所示,
import React from 'react';  
import './App.css';  
import './css/custom.css';  
import MasterComponent from './components/MasterComponent'  
import { UserProvider } from './components/UserContext';  
  
function App() {  
  return (  
    <div className="App">  
      {/* <UserProvider> */}  
        <MasterComponent />  
      {/* </UserProvider> */}  
    </div>  
  );  
}  
  
export default App;  

输出将如下所示,

在使用上下文时,我们只能传递一个值,对于多个值,我们需要使用多个上下文。

还有一种使用上下文类型属性访问上下文值的方法。

首先我们需要从 UserContext.js 文件中导出 UserContext,

import React from 'react'    
const UserContext = React.createContext('Guest')      
const UserProvider = UserContext.Provider      
const UserConsumer = UserContext.Consumer      
export {UserProvider,UserConsumer}    
export default UserContext     

现在我们将使用 HomeComponent.js 中的 contextType 使用上下文值

import React, { Component } from 'react'  
import ProfileComponent from './ProfileComponent'  
import UserContext from './UserContext'  
  
class HomeComponent extends Component {  
    render() {  
        return (  
            <div>  
                Home Component {this.contextType}  
                <ProfileComponent/>  
            </div>  
        )  
    }  
}  
  
HomeComponent.contextType = UserContext  
  
export default HomeComponent

输出将如下所示,

访问多个上下文值,
import React from 'react'      
const UserContext = React.createContext('Guest')    
const ThemeContext = React.createContext('theme')    
const UserProvider = UserContext.Provider    
const UserConsumer = UserContext.Consumer    
const ThemeProvider = ThemeContext.Provider    
const ThemeConsumer = ThemeContext.Consumer    
export {UserProvider,UserConsumer,ThemeConsumer,ThemeProvider}    
export default UserContext    
并在 App.js 中使用它,
import React from 'react';  
import './App.css';  
import './css/custom.css';  
import MasterComponent from './components/MasterComponent'  
import { UserProvider,ThemeProvider } from './components/UserContext';  
  
function App() {  
  return (  
    <div className="App">  
      <UserProvider value="New User">  
        <ThemeProvider value="red">  
        <MasterComponent />  
        </ThemeProvider>  
      </UserProvider>  
    </div>  
  );  
}  
  
export default App;  

现在消耗 ProfileComponent.js 文件中 ThemeProvider 的值,

import React, { Component } from 'react'  
import { UserConsumer,ThemeConsumer } from './UserContext';  
  
class ProfileComponent extends Component {  
    render() {  
        return (  
           <UserConsumer>  
               {  
                   username => (  
                    <ThemeConsumer>  
                    {color => (  
                         <div style={{ color: color }}>Hello {username}</div>  
                    )}           
                    </ThemeConsumer>         
               )}  
           </UserConsumer>  
        )  
    }  
}  
  
export default ProfileComponent  

输出将显示如下,

上下文的限制 

  1. 上下文只能与类组件一起使用。
  2. 使用上下文类型只能访问单个上下文值。为了访问多个值,我们需要使用嵌套的消费者上下文。

概括

在本文中,我们了解了 Render Props 和 Context 的概念及其在 React 中的用法。您可以下载本文附带的源代码。现在在下一篇文章中,我们将学习 HTTP 的一些高级概念以及如何在 React 中使用 Get 和 Post 方法从服务器获取数据。

下一部分 – HTTP 和 React


慕源网 » React js教程(14):在 ReactJS 中渲染属性(Render Props)和上下文(Content)

常见问题FAQ

程序仅供学习研究,请勿用于非法用途,不得违反国家法律,否则后果自负,一切法律责任与本站无关。
请仔细阅读以上条款再购买,拍下即代表同意条款并遵守约定,谢谢大家支持理解!

发表评论

开通VIP 享更多特权,建议使用QQ登录