React初学者指南:继承公共Props与方法的最佳实践
实现 React 中类似抽象类的公共父组件方案
作为 React 开发者,我完全理解你想要复用公共逻辑、让子组件灵活定制的需求——这在 React 里可以通过两种主流方式实现,既可以贴近你熟悉的“抽象类”思路,也能遵循 React 推荐的组合模式。下面分两种场景详细说明:
一、类组件方案(贴近 Java 抽象类思路)
如果还在使用类组件,可以创建一个抽象基类组件,定义公共 Props、方法和基础渲染逻辑,子组件继承后按需重写或扩展。
1. 创建公共父组件(抽象基类)
这个组件只实现通用逻辑,留出“抽象方法”让子组件必须实现核心输入部分:
import React, { Component } from 'react'; import PropTypes from 'prop-types'; class BaseInput extends Component { // 定义公共Props的类型约束 static propTypes = { label: PropTypes.string.isRequired, value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), onChange: PropTypes.func.isRequired, disabled: PropTypes.bool, }; // 公共默认Props static defaultProps = { disabled: false, }; // 公共方法:通用值格式化逻辑,子组件可重写 formatValue = (value) => String(value); // 公共UI:渲染通用标签 renderLabel = () => <label>{this.props.label}</label>; // 抽象方法:子组件必须实现的核心输入渲染 renderInput = () => { throw new Error('子组件必须实现 renderInput 方法'); }; // 基础渲染框架 render() { const { disabled } = this.props; return ( <div className="input-wrapper" style={{ opacity: disabled ? 0.6 : 1 }}> {this.renderLabel()} {this.renderInput()} </div> ); } }
2. 实现数字输入子组件
继承基类后,你可以灵活添加专属 Props、重写默认值和公共方法:
import React from 'react'; import BaseInput from './BaseInput'; import PropTypes from 'prop-types'; class NumberInput extends BaseInput { // 扩展专属Props的类型约束 static propTypes = { ...BaseInput.propTypes, min: PropTypes.number, max: PropTypes.number, }; // 设置数字输入的专属默认值 static defaultProps = { ...BaseInput.defaultProps, min: 0, max: 100, }; // 重写格式化方法:只保留有效数字 formatValue = (value) => { const num = parseInt(value, 10); return isNaN(num) ? this.props.min : Math.max(this.props.min, Math.min(this.props.max, num)); }; // 实现核心输入渲染 renderInput = () => { const { value, onChange, disabled, min, max } = this.props; const handleChange = (e) => onChange(this.formatValue(e.target.value)); return ( <input type="number" value={value} onChange={handleChange} disabled={disabled} min={min} max={max} /> ); }; }
3. 实现日期输入子组件
同样的逻辑,日期输入可以忽略数字输入的 min/max Props,只保留公共部分并添加专属配置:
import React from 'react'; import BaseInput from './BaseInput'; import PropTypes from 'prop-types'; class DateInput extends BaseInput { // 只扩展日期专属Props static propTypes = { ...BaseInput.propTypes, format: PropTypes.string, }; static defaultProps = { ...BaseInput.defaultProps, format: 'YYYY-MM-DD', }; // 重写格式化方法:处理日期格式(示例简化,实际可搭配 date-fns/moment) formatValue = (value) => value; renderInput = () => { const { value, onChange, disabled } = this.props; return ( <input type="date" value={value} onChange={(e) => onChange(e.target.value)} disabled={disabled} /> ); }; }
二、函数组件方案(React 现代推荐模式)
现在 React 更推荐组合而非继承,我们可以用「自定义 Hook 提取公共逻辑 + 公共 UI 组件承载布局」的方式,既实现复用,又保持子组件的灵活性。
1. 创建公共逻辑 Hook
提取输入组件的通用逻辑,子组件可以直接调用或重写:
import { useCallback } from 'react'; export const useBaseInput = (props) => { const { value, onChange, disabled } = props; // 通用格式化方法,子组件可覆盖 const formatValue = useCallback((inputValue) => String(inputValue), []); // 通用变更处理逻辑 const handleBaseChange = useCallback( (inputValue) => onChange(formatValue(inputValue)), [onChange, formatValue] ); return { disabled, handleBaseChange, formatValue }; };
2. 创建公共布局组件
承载通用的标签、容器样式,子组件只需传入核心输入部分:
export const BaseInputLayout = ({ label, children, disabled }) => { return ( <div className="input-wrapper" style={{ opacity: disabled ? 0.6 : 1 }}> <label>{label}</label> {children} </div> ); };
3. 实现数字输入子组件
组合公共 Hook 和布局组件,灵活定制专属逻辑:
import { useCallback } from 'react'; import { useBaseInput, BaseInputLayout } from './BaseInput'; export const NumberInput = ({ label, value, onChange, disabled, min = 0, max = 100 }) => { const { disabled: baseDisabled } = useBaseInput({ value, onChange, disabled }); // 自定义数字格式化逻辑 const formatNumber = useCallback( (inputValue) => { const num = parseInt(inputValue, 10); return isNaN(num) ? min : Math.max(min, Math.min(max, num)); }, [min, max] ); const handleChange = useCallback( (e) => onChange(formatNumber(e.target.value)), [onChange, formatNumber] ); return ( <BaseInputLayout label={label} disabled={baseDisabled}> <input type="number" value={value} onChange={handleChange} disabled={baseDisabled} min={min} max={max} /> </BaseInputLayout> ); };
核心优势总结
- 类组件方案:贴近面向对象的抽象类思路,适合习惯继承模式的开发者,但要注意避免组件过度耦合。
- 函数组件方案:符合 React 现代设计理念,通过 Hook 提取逻辑、组合组件实现复用,灵活性更高,是官方推荐的方式。
- Props 灵活性:两种方案都支持子组件自由扩展、重写默认值或忽略不需要的公共 Props,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Rahul Bansal
相关产品推荐
相关产品推荐

