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

React中是否存在Solid.js的mergeProps与splitProps等价方法?

React中替代Solid.js的mergeProps与splitProps的方案

一、替代mergeProps的方案

Solid.js的mergeProps会智能合并props对象:事件处理器按顺序执行、className/style自动合并而非覆盖。在React生态中,**React Aria的mergeProps**完全匹配这个功能,它专门针对React组件的props合并做了优化:

  1. 安装依赖(若未安装):
npm install react-aria
  1. 导入并使用,用法和Solid.js版本完全一致:
import { mergeProps } from 'react-aria';

const propsWithDefault = mergeProps({ as: component }, props);

如果不想依赖第三方库,也可以自定义简易版mergeProps,覆盖核心合并逻辑:

function mergeProps(...sources) {
  const result = {};
  for (const source of sources) {
    if (!source) continue;
    for (const key in source) {
      if (key === 'className') {
        result.className = [result.className, source.className].filter(Boolean).join(' ');
      } else if (key === 'style') {
        result.style = { ...result.style, ...source.style };
      } else if (typeof source[key] === 'function' && typeof result[key] === 'function') {
        // 合并事件处理器,按顺序执行
        const prevHandler = result[key];
        result[key] = (...args) => {
          prevHandler(...args);
          source[key](...args);
        };
      } else {
        result[key] = source[key];
      }
    }
  }
  return result;
}

二、自定义实现splitProps

Solid.js的splitProps可以将单个props对象拆分为多个子集,指定键的子集单独提取,剩余键归最后一个返回值。React没有内置该功能,可自行实现:

function splitProps(props, ...keysArrays) {
  const result = [];
  const remaining = { ...props };

  for (const keys of keysArrays) {
    const subset = {};
    for (const key of keys) {
      if (remaining.hasOwnProperty(key)) {
        subset[key] = remaining[key];
        delete remaining[key];
      }
    }
    result.push(subset);
  }

  result.push(remaining);
  return result;
}

用法和Solid.js版本完全一致:

const [local, styleProps, others] = splitProps(
  propsWithDefault,
  ["as", "class", "className", "__baseStyle"],
  usedStylePropNames
);

三、迁移代码的修改示例

替换原Solid.js的mergeProps/splitProps导入,修改后的核心代码片段如下:

import React, { FC, ReactNode, useMemo } from "react";
import { mergeProps } from "react-aria";
import { createStyledSystemClass, getUsedStylePropNames } from "../styled-system/system";
import { isFunction } from "../utils/assertion";
import { classNames, createClassSelector } from "../utils/css";

// 自定义splitProps函数
function splitProps(props, ...keysArrays) {
  const result = [];
  const remaining = { ...props };

  for (const keys of keysArrays) {
    const subset = {};
    for (const key of keys) {
      if (remaining.hasOwnProperty(key)) {
        subset[key] = remaining[key];
        delete remaining[key];
      }
    }
    result.push(subset);
  }

  result.push(remaining);
  return result;
}

const styled: HopeFactory = <T extends ElementType>(
  component: T,
  styleOptions?: HopeFactoryStyleOptions<T>
) => {
  const hopeComponent: HopeComponent<T> = props => {
    const usedStylePropNames = getUsedStylePropNames(props);

    const propsWithDefault = mergeProps({ as: component }, props);

    const [local, styleProps, others] = splitProps(
      propsWithDefault as HTMLHopeProps<any>,
      ["as", "class", "className", "__baseStyle"],
      usedStylePropNames
    );

    const __baseStyles = useMemo(() => {
      const factoryBaseStyle = isFunction(styleOptions?.baseStyle)
        ? styleOptions?.baseStyle(props as any)
        : styleOptions?.baseStyle;
      return [factoryBaseStyle, local.__baseStyle];
    },[local.__baseStyle, props]);

    const classes = () => classNames(
      styleOptions?.baseClass,
      local.class,
      local.className,
      createStyledSystemClass(styleProps, __baseStyles)
    );

    // 修复Dynamic组件的逻辑问题
    const Dynamic: FC<{ as: ElementType, children: ReactNode, ...restProps }> = ({ as: Component, children, ...restProps }) => {    
      return React.createElement(Component || 'div', restProps, children);
    };

    return <Dynamic as={local.as} className={classes()} {...others}>{props.children}</Dynamic>;
  };

  hopeComponent.toString = () =>
    styleOptions?.baseClass ? createClassSelector(styleOptions.baseClass) : "";

  return hopeComponent;
};

// 后续factory和hope导出逻辑保持不变

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:16:11