You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React/TypeScript基础:如何将代码拆分至独立组件?

React组件拆分入门:物流计算器优化方案

针对你的物流计算器组件拆分需求,这里给你一套简单易懂的入门方案,核心围绕单一职责原则来拆分代码:每个组件只负责一件事,逻辑和UI尽量分离。


1. 封装购物车价值输入组件(CartValueInput)

把购物车价值的输入框、值的处理,以及和cartValue相关的附加费计算逻辑都塞进这个组件里,通过回调把值传递给父组件,让App组件不用关心这部分的细节。

import { useState } from 'react';

// 定义组件接收的参数类型
type CartValueProps = {
  onValueChange: (value: number) => void;
  // 可选:如果父组件需要用到计算后的附加费,可以加这个回调
  onSurchargeChange?: (surcharge: number) => void;
};

function CartValueInput({ onValueChange, onSurchargeChange }: CartValueProps) {
  const [localValue, setLocalValue] = useState(0);

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const inputValue = parseFloat(e.target.value) || 0;
    setLocalValue(inputValue);
    // 把输入值传递给父组件
    onValueChange(inputValue);

    // 原本在App里的surcharge计算逻辑移到这里
    const surcharge = inputValue < 100 ? 10 - inputValue : 30;
    onSurchargeChange?.(surcharge);
  };

  return (
    <div>
      <label>购物车价值</label>
      <input 
        type="number" 
        value={localValue} 
        onChange={handleInputChange}
      />€ 
      <br />
    </div>
  );
}

export default CartValueInput;

2. 封装计算按钮组件(CalculateFeeButton)

把提交按钮单独封装成组件,这样按钮的样式、文本都可以灵活配置,同时把提交逻辑通过回调交给父组件处理,保持组件的通用性。

type CalculateButtonProps = {
  onSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
  buttonText?: string;
};

function CalculateFeeButton({ onSubmit, buttonText = "计算配送费用" }: CalculateButtonProps) {
  return (
    <button type="submit" onClick={(e) => onSubmit(e)}>
      {buttonText}
    </button>
  );
}

export default CalculateFeeButton;

3. 提取配送费用计算逻辑为独立纯函数

把原本写在handleSubmit里的核心计算逻辑抽成单独的纯函数,这样不仅复用性高,还方便单独测试,也让App组件的代码更清爽。

// 定义计算参数的类型
type FeeCalcParams = {
  cartValue: number;
  deliveryDistance: number;
};

export function calculateDeliveryFee({ cartValue, deliveryDistance }: FeeCalcParams): number {
  const baseFee = 5;
  let additionalFee = 5;

  if (deliveryDistance > 1000) {
    additionalFee = Math.ceil((deliveryDistance - 1000) / 500);
    additionalFee = additionalFee > 0 ? additionalFee : 1;
  }

  // 如果需要把surcharge加到总费用里,可以在这里加上
  // const surcharge = cartValue < 100 ? 10 - cartValue : 30;
  // return baseFee + additionalFee + surcharge;

  return baseFee + additionalFee;
}

4. 重构后的App组件

把拆分好的组件和函数整合起来,App组件只需要负责管理全局状态和协调各个子组件:

import { useState } from 'react';
import CartValueInput from './CartValueInput';
import CalculateFeeButton from './CalculateFeeButton';
import { calculateDeliveryFee } from './calculateDeliveryFee';

function App() {
  const [cartValue, setCartValue] = useState(0);
  const [deliveryDistance, setDeliveryDistance] = useState(0);
  const [fee, setFee] = useState(0);

  const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    // 调用独立的计算函数得到结果
    const totalFee = calculateDeliveryFee({ cartValue, deliveryDistance });
    setFee(totalFee);
  };

  return (
    <div>
      <h1>计算配送费用</h1>
      <form onSubmit={handleFormSubmit}>
        <CartValueInput onValueChange={setCartValue} />
        
        <label>配送距离</label> 
        <input 
          type="number"
          value={deliveryDistance}
          onChange={(e) => setDeliveryDistance(parseFloat(e.target.value) || 0)}
        />英里
        
        <CalculateFeeButton onSubmit={handleFormSubmit} />
      </form>
      <h3>配送费用:{fee} USD</h3>
    </div>
  );
}

export default App;

拆分思路总结

  • UI与逻辑分离:输入、按钮这类UI组件只负责渲染和传递交互,核心计算逻辑放在纯函数里。
  • Props传递:子组件通过props接收父组件的状态更新回调,把用户输入或计算结果回传给父组件。
  • 单一职责:每个组件只聚焦一件事,比如CartValueInput只处理购物车价值的输入和相关计算,避免App组件臃肿。

内容的提问来源于stack exchange,提问作者KJM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 00:30:39