MST

星途 面试题库

面试题:React组件设计模式:函数式与类组件的融合应用

在一个复杂的React项目中,有时需要融合函数式组件和类组件的优势来进行开发。请描述一种场景,在该场景下这种融合会带来显著的好处,并阐述如何在项目中设计和实现这种融合,包括如何处理组件间通信和状态共享等问题。
41.8万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

适用场景

例如在开发一个电商产品详情页时,产品基本信息展示部分(如标题、价格等)变化频率低,适合用函数式组件,因为它简洁、性能好。而涉及复杂交互,如库存实时更新、加入购物车操作等需要管理复杂状态和生命周期的部分,适合用类组件。这样融合可以在保证基础展示性能的同时,高效处理复杂交互逻辑。

设计与实现

  1. 函数式组件:使用 React.memo 包裹函数式组件,以实现浅比较优化,避免不必要的渲染。例如:
import React from'react';

const ProductInfo = React.memo(({ product }) => {
  return (
    <div>
      <h1>{product.title}</h1>
      <p>Price: {product.price}</p>
    </div>
  );
});

export default ProductInfo;
  1. 类组件:继承 React.Component,在 state 中管理交互相关状态,在 componentDidMountcomponentDidUpdate 等生命周期方法中处理副作用。例如:
import React, { Component } from'react';

class ProductInteraction extends Component {
  constructor(props) {
    super(props);
    this.state = {
      stock: this.props.product.stock,
      isAddedToCart: false
    };
  }

  componentDidMount() {
    // 模拟获取实时库存更新
    setInterval(() => {
      // 假设从服务器获取新库存数据
      const newStock = this.props.product.stock - 1;
      this.setState({ stock: newStock });
    }, 5000);
  }

  addToCart = () => {
    this.setState({ isAddedToCart: true });
  };

  render() {
    return (
      <div>
        <p>Stock: {this.state.stock}</p>
        <button onClick={this.addToCart}>Add to Cart</button>
        {this.state.isAddedToCart && <p>Added to cart!</p>}
      </div>
    );
  }
}

export default ProductInteraction;
  1. 组件组合:在父组件中组合这两种组件。
import React from'react';
import ProductInfo from './ProductInfo';
import ProductInteraction from './ProductInteraction';

const product = {
  title: 'Sample Product',
  price: 100,
  stock: 10
};

const ProductPage = () => {
  return (
    <div>
      <ProductInfo product={product} />
      <ProductInteraction product={product} />
    </div>
  );
};

export default ProductPage;

组件间通信与状态共享

  1. 父子组件通信:通过 props 传递数据。如 ProductPageProductInfoProductInteraction 传递 product 数据。
  2. 状态提升:若子组件间需要共享状态,将状态提升到共同父组件。例如,若 ProductInteraction 中添加到购物车后需要更新 ProductInfo 中的显示状态,可以在 ProductPage 中管理 isAddedToCart 状态,再通过 props 传递给两个子组件。
import React, { useState } from'react';
import ProductInfo from './ProductInfo';
import ProductInteraction from './ProductInteraction';

const product = {
  title: 'Sample Product',
  price: 100,
  stock: 10
};

const ProductPage = () => {
  const [isAddedToCart, setIsAddedToCart] = useState(false);

  const addToCart = () => {
    setIsAddedToCart(true);
  };

  return (
    <div>
      <ProductInfo product={product} isAddedToCart={isAddedToCart} />
      <ProductInteraction product={product} addToCart={addToCart} isAddedToCart={isAddedToCart} />
    </div>
  );
};

export default ProductPage;
  1. 使用Context(适用于深层嵌套组件间通信):创建 Context,在顶层组件提供数据,深层组件消费数据。例如,创建一个全局的购物车状态 Context
import React, { createContext, useState } from'react';

const CartContext = createContext();

const CartProvider = ({ children }) {
  const [cartItems, setCartItems] = useState([]);

  const addItemToCart = (item) => {
    setCartItems([...cartItems, item]);
  };

  return (
    <CartContext.Provider value={{ cartItems, addItemToCart }}>
      {children}
    </CartContext.Provider>
  );
};

export { CartContext, CartProvider };

在需要的组件中消费 Context

import React from'react';
import { CartContext } from './CartContext';

const SomeDeepComponent = () => {
  const { cartItems, addItemToCart } = React.useContext(CartContext);

  return (
    <div>
      <p>Cart items: {cartItems.length}</p>
      <button onClick={() => addItemToCart({ name: 'New Item' })}>Add to Cart from deep</button>
    </div>
  );
};

export default SomeDeepComponent;
  1. 使用状态管理库(如Redux):当项目规模较大,状态管理复杂时,引入Redux。定义 actionreducer 来管理状态,通过 connectuseSelectoruseDispatch 等方式连接组件与状态。例如:
// actions.js
const ADD_TO_CART = 'ADD_TO_CART';

export const addToCart = (product) => ({
  type: ADD_TO_CART,
  payload: product
});

// reducer.js
const initialState = {
  cart: []
};

const cartReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TO_CART:
      return {
      ...state,
        cart: [...state.cart, action.payload]
      };
    default:
      return state;
  }
};

export default cartReducer;

// store.js
import { createStore } from'redux';
import cartReducer from './reducer';

const store = createStore(cartReducer);

export default store;

// 组件中使用
import React from'react';
import { useSelector, useDispatch } from'react-redux';
import { addToCart } from './actions';

const ProductComponent = () => {
  const cart = useSelector(state => state.cart);
  const dispatch = useDispatch();
  const product = { name: 'Sample Product' };

  const handleAddToCart = () => {
    dispatch(addToCart(product));
  };

  return (
    <div>
      <p>Cart items: {cart.length}</p>
      <button onClick={handleAddToCart}>Add to Cart</button>
    </div>
  );
};

export default ProductComponent;