设计模式:HOC + renderProps | 豆包MarsCode AI刷题

56 阅读5分钟

render props模式

render props 是一种在React组件之间传递一个名为 render 的函数的模式,这个函数返回一个React元素。render props 模式允许组件通过其props接收一个函数,该函数负责决定组件如何渲染。这种方法提供了一种高度灵活的方式来构建可重用的组件。

示例:

假设我们有一个 Button 组件,我们想要根据不同的条件渲染不同的按钮样式或行为:

// ButtonWithRenderProp.js
import React from 'react';
​
const ButtonWithRenderProp = ({ render }) => {
  const onClick = () => {
    console.log('Button clicked!');
  };
​
  return (
    <div>
      {render({ onClick })}
    </div>
  );
};
​
export default ButtonWithRenderProp;

现在,我们可以这样使用这个组件:

// App.js
import React from 'react';
import ButtonWithRenderProp from './ButtonWithRenderProp';
​
const App = () => {
  return (
    <ButtonWithRenderProp
      render={({ onClick }) => (
        <button onClick={onClick} style={{ background: 'blue', color: 'white' }}>
          Click me!
        </button>
      )}
    />
  );
};
​
export default App;

在这个例子中,ButtonWithRenderProp 组件接收一个 render 函数作为prop,这个函数接收一个对象,其中包含一个 onClick 函数。然后,render 函数返回一个按钮元素,它使用传递进来的 onClick 函数。

render props 的特点:
  1. 动态渲染:组件可以动态决定如何渲染,基于传递给它的 render 函数。
  2. 解耦组件render props 允许你将组件的行为(通过 render 函数)与其结构(组件本身的JSX)解耦。
  3. 可组合性:使用 render props,你可以轻松地组合多个组件,每个组件都可以贡献一部分渲染逻辑。
使用场景:
  • 动态组件:当你需要基于某些条件渲染不同的组件时。
  • 抽象UI:当你想要创建一个组件,它可以适应多种不同的渲染需求时。
  • 传递行为:当你想要将渲染逻辑作为props传递给子组件时。

render props模式最重要的是它返回一个react元素,比如我将上面的render属性改名,依然有效。

import React from 'react';
​
const SharedComponentWithGoofyName extends React.Component {
  render() {
    return (
      <div>
        {this.props.wrapThisThingInADiv()}
      </div>
    );
  }
}
​
const SayHelloWithGoofyName = () => (
  <SharedComponentWithGoofyName wrapThisThingInADiv={() => (
    <span>hello!</span>
  )} />
);

HOC设计模式

高阶组件(Higher Order Component,HOC)是React中用于重用组件逻辑的一种高级技术。它本身不是一个React组件,而是一个函数,这个函数接受一个组件作为参数,并返回一个新的组件。HOC让你能够重用组件之间的代码,如事件处理、订阅数据源、注入主题等,而不必在每个组件中重复这些代码。

高阶组件在React生态链技术中经常用到,对读者较为熟悉的,比如Redux中的connect,React Router中的withRouter等。

HOC的主要特点:
  1. 参数传递:HOC接收一个组件作为参数。
  2. 返回组件:HOC返回一个新的组件。
  3. 可重用性:通过HOC,你可以创建可重用的组件逻辑。
  4. 无侵入性:HOC不会修改传入的组件,也不会使用继承,因此它们可以更容易地进行测试,并且可以保持干净。
使用场景:
  • 代码复用:当多个组件需要相同的功能时,可以使用HOC来避免重复代码。
  • 动态props注入:HOC可以添加新的props到组件,或者修改传递给子组件的props。
  • 渲染劫持:HOC可以在渲染组件之前或之后执行操作。
  • 关注点分离:将组件的业务逻辑和UI分离,使得组件更加专注于UI的展示。
代码示例
import React from 'react';
​
// 假设的认证服务,用于模拟检查登录状态
const AuthService = {
  isAuthenticated: () => {
    // 这里可以是异步操作,比如从localStorage获取token,然后验证token的有效性
    // 模拟检查localStorage中是否有token
    const token = localStorage.getItem('userToken');
    return !!token; // 如果有token,返回true,表示用户已登录
  }
};
​
function withAuth(WrappedComponent) {
  return class extends React.Component {
    render() {
      const isLoggedIn = AuthService.isAuthenticated();
​
      return <WrappedComponent isLoggedIn={isLoggedIn} {...this.props} />;
    }
  };
}
​
// 示例组件,使用HOC注入的isLoggedIn prop
class SomeComponent extends React.Component {
  render() {
    const { isLoggedIn } = this.props;
    if (isLoggedIn) {
      return <div>Welcome, you are logged in!</div>;
    } else {
      return <div>Please log in to continue.</div>;
    }
  }
}
​
const AuthenticatedComponent = withAuth(SomeComponent);
​
export default AuthenticatedComponent;
相同点:
  1. 组件复用:HOC和Render Props都是用于实现组件复用的技术,使得我们可以在多个组件之间共享功能。
  2. 非侵入性:它们都是以非侵入性的方式添加功能到现有组件,不需要修改原始组件的代码。
不同点:
  1. 抽象层级:HOC是一种在React中复用组件逻辑的高级技术。它实际上是一个函数,接受一个组件作为参数,并返回一个新的组件。这种方式可以使得组件逻辑与原始组件解耦,但可能会产生嵌套层级。 Render Props是通过props将一个函数传递给组件,这个函数允许组件在渲染时获取到特定的数据或行为。这样可以更加灵活地控制组件的行为。
  2. 组件结构:使用HOC时,我们在组件之外创建一个包裹组件,它会对原始组件进行包装,从而添加额外的功能。这意味着我们需要编写一个高阶函数来创建新的组件。 使用Render Props时,我们在组件内部定义一个特定的prop,它是一个函数,用于传递所需的功能或数据。这种方式更加直接,不需要额外的高阶函数。
  3. 数据流:HOC可以通过props将数据传递给被包装的组件,但它不能直接访问被包装组件的state。在HOC中,数据流是从外部向内部。 Render Props允许组件在渲染过程中向内部传递数据,通常是通过props中的回调函数。在Render Props中,数据流是从内部向外部。