React 之 render props 的理解

1.基本概念

在调用组件时,引入一个函数类型的 prop,这个 prop定义了组件的渲染方式。

 

2.回调渲染

回顾组件通信的几种方式

父-> 子 props

子-> 父 回调、消息通道

任意 状态提升、Context、Redux 等

而 render props 本质实际上是使用到了回调的方式来通信。只不过在传统的 js 回调是在构造函数中进行初始化(使用回调函数作为参数),而在 react 中,现在可以通过 props 传入该回调函数,就是我们所介绍的 render prop。

从结果论来说,回调的目的是渲染子组件,而渲染的外部细节需要通过父组件注入,实现了控制反转。

扫描二维码关注公众号,回复: 6420943 查看本文章

 从目的论来说,我们的目的是组件复用。它实现 了内部细节封装,并将外部细节(通过回调函数的形式 )暴露,达到了灵活复用的目的。

 

3.著名应用实例:

React Router 、 Downshift 和 react-motion 

 

4.举例说明

示例1:

依赖 props.children 渲染组件,把控制权交给上层组件,子 组件实现控制反转。

子组件

import React, { Component } from "react";

export class ScrollPos extends Component {
  state = {
    position: null
  };

  componentDidMount() {
    window.addEventListener("scroll", this.handleScroll);
  }

  componentWillUnmount() {
    window.removeEventListener("scroll", this.handleScroll);
  }

  handleScroll = e => {
    const scrollTop = e.target.scrollingElement.scrollTop;
    this.setState((state, props) => {
      return { position: scrollTop };
    });
  };

  render() {
    return <div className='scroll'>{this.props.children(this.state.position)}</div>;
  }
}

export default ScrollPos;

父组件

import React from "react";
import "./App.css";
import ScrollPos from "./component/ScrollPos";

function App() {
  return (
    <div className="App">
      <ScrollPos>
        {position => <h1>{"Awesome !".substr(0, position * 15)}</h1>}
      </ScrollPos>
      <div className="spacer" />
    </div>
  );
}

export default App;

示例2:

使用 props 传回调函数,需要多少回调就需要设置多少个 prop,比如这里 Auth 子组件既需要登录成功回调又需要登录失败回调。

子组件

const Auth= (props) => {
  const userName = getUserName();

  if (userName) {
    const allProps = {userName, ...props};
    return (
      <React.Fragment>
        {props.login(allProps)}
      </React.Fragment>
    );
  } else {
    <React.Fragment>
      {props.nologin(props)}
    </React.Fragment>
  }
};

父组件

<Auth
    login={({userName}) => <h1>Hello {userName}</h1>}
    nologin={() => <h1>Please login</h1>}
  />

5.浅比较性能优化

如果在父组件中传递 props时 使用箭头函数,每次都会生成新的函数,造成传递给子组件的 props 每次都是新的,引起子组件重新渲染(子组件继承 PureComponent 无效)。因此考虑不使用箭头函数转为使用实例属性的方式:

class MouseTracker extends React.Component {
  // 定义为实例方法,`this.renderTheCat`始终
  // 当我们在渲染中使用它时,它指的是相同的函数
  renderTheCat(mouse) {
    return <Cat mouse={mouse} />;
  }

  render() {
    return (
      <div>
        <h1>Move the mouse around!</h1>
        <Mouse render={this.renderTheCat} />
      </div>
    );
  }
}

  

233

猜你喜欢

转载自www.cnblogs.com/lemos/p/11006959.html