高阶组件

高阶组件指的不是组件,而是一个函数,它可以增强组件,它接收一个组件,返回一个新组件,这个新组件是接收组件的加强版。假设有这样三个组件

  1. class App1 extends React.Component {
  2. state = { data: null };
  3. componnetDidMount() {
  4. const data = localStorage.getItem("data");
  5. this.setState({
  6. data
  7. });
  8. }
  9. render() {
  10. return <div>{this.state.data}</div>;
  11. }
  12. }
  13. class App2 extends React.Component {
  14. state = { data: null };
  15. componnetDidMount() {
  16. const data = localStorage.getItem("data");
  17. this.setState({
  18. data
  19. });
  20. }
  21. render() {
  22. return <div>{this.state.data}</div>;
  23. }
  24. }
  25. class App3 extends React.Component {
  26. state = { data: null };
  27. componnetDidMount() {
  28. const data = localStorage.getItem("data");
  29. this.setState({
  30. data
  31. });
  32. }
  33. render() {
  34. return <div>{this.state.data}</div>;
  35. }
  36. }

观察这三个组件,它们都有一个共同的特点,那就是它们在挂载后都要从localStorage中获取数据,可见这样的代码是重复了的,我们如果每次要从localStorage获取数据,都要写一遍这样的代码,那怎么可以让这样的逻辑复用呢? 这就是高阶组件的作用,考虑下面这样的一个函数

  1. function getDataFromLocalStorage(WrapComponent) {
  2. class NewComponent extends React.Component {
  3. state = { data: null };
  4. componentDidComponent() {
  5. const data = localStorage.getItem("data");
  6. this.setState({
  7. data
  8. });
  9. }
  10. render() {
  11. return <WrapComponent data={this.state.data} />
  12. }
  13. }
  14. return NewComponent
  15. }

该函数接收一个组件,返回一个新组件。这个新组件在挂载后会用localStorage读取数据,并注入到传入的组件的props.data中。而这个传入的组件会作为新组件render函数的返回值,所以当我们使用这个新组件时,与使用传入的组件一致,不过此时新组件的props中已经有了从localStorage读取的数据。我们可以将上面的三个组件都可以改造为

  1. class App1 extends React.Component {
  2. render() {
  3. return <div>{this.props.data}</div>
  4. }
  5. App1 = getDataFromLocalStorage(App1)
  6. }
  7. class App2 extends React.Component {
  8. render() {
  9. return <div>{this.props.data}</div>
  10. }
  11. App2 = getDataFromLocalStorage(App2)
  12. }
  13. class App3 extends React.Component {
  14. render() {
  15. return <div>{this.props.data}</div>
  16. }
  17. App3 = getDataFromLocalStorage(App3)
  18. }

我们使用高阶函数为三个组件的props.data中注入了数据,这样三个组件只要调用这个方法,就可以自动可以在props中获取到数据,从而达到了代码的复用。可能读到这里你还不能理解,没关系,多读几遍好好消化,或者写个几遍就习惯了。

render props

render props的目的同样也是进行代码的复用。再次考虑上面代码的复用,不过这次使用render props实现代码的复用

  1. class GetDataFromLocalStorage extends React.Component {
  2. state = {data: null}
  3. componentDidMount() {
  4. this.setState(localStorage.getItem("data"))
  5. }
  6. render() {
  7. return {this.props.render(this.state)}
  8. }
  9. }
  10. class App extends React.Component {
  11. render() {
  12. return (
  13. <GetDataFromLocalStorage
  14. render = {({data}) => {
  15. return <div>data</div>
  16. }}
  17. />
  18. )
  19. }
  20. }

仔细阅读上面的代码,想必还是比较容易读懂的。Render Props的核心思想是,通过一个函数将class组件的state作为props传递给纯函数组件。