类组件复用逻辑的方法

200 阅读2分钟

在 React 中,类组件复用逻辑的方法主要包括高阶组件(Higher-Order Components, HOCs)和 Render Props。这两种模式都可以帮助我们在多个组件之间共享逻辑,但它们的实现方式和使用场景有所不同。

高阶组件(Higher-Order Components, HOCs)

高阶组件是一种用于复用组件逻辑的技术。它本质上是一个函数,接收一个组件并返回一个新的组件。HOCs 可以在不修改原组件的情况下增强组件的功能。

示例代码 假设我们有一个需求,需要在多个组件中添加用户认证逻辑。

import React, { Component } from 'react';

// 高阶组件
const withAuth = (WrappedComponent) => {
  return class extends Component {
    componentDidMount() {
      // 模拟认证逻辑
      const isAuthenticated = true; // 假设用户已认证
      if (!isAuthenticated) {
        // 未认证时的处理逻辑
        console.log('User is not authenticated');
      }
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  };
};

// 原始组件
class Dashboard extends Component {
  render() {
    return <div>Dashboard Content</div>;
  }
}

// 包装后的组件
const DashboardWithAuth = withAuth(Dashboard);

export default DashboardWithAuth;

Render Props

Render Props 是一种通过一个函数将要渲染的内容传递给组件的技术。它允许我们在组件之间共享逻辑,而无需使用高阶组件。

示例代码 假设我们有一个需求,需要在多个组件中添加用户认证逻辑。


class AuthComponent extends Component {
    componentDidMount() {
        // 模拟认证逻辑
        const isAuthenticated = true; // 假设用户已认证
        if (!isAuthenticated) {
            // 未认证时的处理逻辑
            console.log('User is not authenticated');
        }
    }

    render() {
        return this.props.render();
    }
};

// 原始组件
class Dashboard extends Component {
  render() {
    return <div>Dashboard Content</div>;
  }
}

// 包装后的组件
const DashboardWithAuth = <AuthComponent render={() => <Dashboard />} />;

export default DashboardWithAuth;

比较与选择

高阶组件(HOCs)

优点:

  • 可以在不修改现有组件的情况下增强组件功能。
  • 适用于需要在多个组件中复用逻辑的场景。

缺点:

  • 可能会导致“嵌套地狱”(Wrapper Hell),即组件层级过深,会造成比较多的问题,例如props丢失的问题,比如使用这样的代码withAuth(withRouter(withUserStatus(UserDetail))),withAuth传递给UserDetail的某个prop可能在withUserStatus组件里面丢失或者被覆盖了。
  • 隐藏了组件的实际层级,使得调试变得困难。

Render Props

优点:

  • 更加灵活,可以动态决定渲染内容。
  • 不会增加组件的层级。

缺点:

  • 可能会导致“函数作为子组件”(Function as Child Component, FaCC)模式,使得代码结构不清晰。
  • 每次渲染都会创建新的函数,可能会影响性能。

React Hooks逻辑复用(推荐)

同样使用React hooks实现上面的例子:


import { useEffect } from 'react';

const useAuth = () => {
  useEffect(() => {
    // 模拟认证逻辑
    const isAuthenticated = true; // 假设用户已认证
    if (!isAuthenticated) {
      // 未认证时的处理逻辑
      console.log('User is not authenticated');
    }
  }, []);
};

const Dashboard = () => {
  useAuth();

  return <div>Dashboard Content</div>;
};

export default Dashboard;

可以看到这种方式复用逻辑更简单,更直观,代码耦合度也更低。