渲染属性模式

2/17/2022 设计模式渲染属性模式

# 渲染属性模式

通过属性将JSX元素传递给组件

# 简介

通过渲染属性我们传递组件,也能实现和高阶组件模式相同的效果,达到服用相同的数据或相同的逻辑。

# 实现

  • Title组件没有自己的模版,接收一个render属性,通过执行render函数来渲染组件
import React from "react";
import { render } from "react-dom";

import "./styles.css";

const Title = (props) => props.render();

render(
  <div className="App">
    <Title
      render={() => (
        <h1>
          <span role="img" aria-label="emoji"></span>
          I am a render prop!{" "}
          <span role="img" aria-label="emoji"></span>
        </h1>
      )}
    />
  </div>,
  document.getElementById("root")
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

这样我们可以很好的复用Title组件,但是这样好像有点脱裤子放屁的感觉,我们接着往下看👇

import React from "react";
import { render } from "react-dom";
import "./styles.css";

const Title = (props) => props.render();

render(
  <div className="App">
    <Title render={() => <h1>✨ First render prop! ✨</h1>} />
    <Title render={() => <h2>🔥 Second render prop! 🔥</h2>} />
    <Title render={() => <h3>🚀 Third render prop! 🚀</h3>} />
  </div>,
  document.getElementById("root")
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 渲染属性

上面的例子,我们只是传递了不同的函数给Title组件来渲染,脱裤子放屁,但是下面这个例子,我们可以避免使用状态提升来达到使用相同的数据的效果

  • 传递个input的render函数都接受一个value属性,该value属性通过input传递,这样我们就可以将数据传递给不同的子组件
function Input(props) {
  const [value, setValue] = useState("");

  return (
    <>
      <input
        type="text"
        value={value}
        onChange={e => setValue(e.target.value)}
        placeholder="Temp in °C"
      />
      {props.render(value)}
    </>
  );
}

export default function App() {
  return (
    <div className="App">
      <h1>☃️ Temperature Converter 🌞</h1>
      <Input
        render={value => (
          <>
            <Kelvin value={value} />
            <Fahrenheit value={value} />
          </>
        )}
      />
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 将Children作为函数

同样,我们可以不通过render属性来复用数据或者逻辑,我们可以通过Children来传递函数,达到服用数据和逻辑的效果

export default function App() {
  return (
    <div className="App">
      <h1>☃️ Temperature Converter 🌞</h1>
      <Input>
        {value => (
          <>
            <Kelvin value={value} />
            <Fahrenheit value={value} />
          </>
        )}
      </Input>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Input(props) {
  const [value, setValue] = useState("");

  return (
    <>
      <input
        type="text"
        value={value}
        onChange={e => setValue(e.target.value)}
        placeholder="Temp in °C"
      />
      {props.children(value)}
    </>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Hooks

在某些情况下,我们可以用钩子替换渲染属性。

# 优点

  • 使用渲染属性模式可以很容易地在多个组件之间共享逻辑和数据。
  • 通过使用渲染属性或孩子属性,组件可以变得非常可重用。
  • 尽管和高阶组件模式主要解决了相同的问题,即可重用性和共享数据,但渲染属性模式解决了我们使用HOC模式可能遇到的一些问题。 使用HOC模式所遇到的命名冲突问题不再适用于使用render props模式,因为我们不会自动合并属性。我们明确地将属性传递给子组件

# 缺点

  • 我们试图通过渲染属性解决的问题已经被React Hooks所取代。
  • Hooks改变了我们为组件添加可重用性和数据共享的方式,在很多情况下,它们可以取代属性渲染模式。
  • 因为我们不能给渲染属性添加生命周期方法,所以我们只能在不需要改变接收数据的组件上使用它。
Last Updated: 2/17/2022, 10:16:58 PM