React 之 render props 的理解


1.基本概念

在調用組件時,引入一個函數類型的 prop,這個 prop定義了組件的渲染方式。

 

2.回調渲染

回顧組件通信的幾種方式

父-> 子 props

子-> 父 回調、消息通道

任意 狀態提升、Context、Redux 等

而 render props 本質實際上是使用到了回調的方式來通信。只不過在傳統的 js 回調是在構造函數中進行初始化(使用回調函數作為參數),而在 react 中,現在可以通過 props 傳入該回調函數,就是我們所介紹的 render prop。

 

從結果論來說,回調的目的是渲染子組件,而渲染的外部細節需要通過父組件注入,實現了控制反轉。

 從目的論來說,我們的目的是組件復用。它實現 了內部細節封裝,並將外部細節(通過回調函數的形式 )暴露,達到了靈活復用的目的。

 

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>
    );
  }
}

*  注:這里也可以直接將 renderTheCat 這個渲染方法變成組件。類似於 下面代碼中的 movies

import Movies from "./components/movies";

<Route path="/movies" component={Movies}/>

 

注:回調的理解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM