npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@mx-design/hooks

v0.1.2

Published

mx-design react hooks lib

Readme

语言

English | 中文

简介

mx-design 中的 React hooks库

文档

useMergeProps

这样的设计参考了arco.design

把我们的组件库对于props的处理分为三层:

举个例子, 如下的Empty组件:

const defaultProps = {};
function Empty(baseProps: EmptyProps, ref) {
  const { getPrefixCls, componentConfig } = useContext(ConfigContext);
  const props = useMergeProps<EmptyProps>(baseProps, defaultProps, componentConfig?.Empty);

  return (
    <div ref={ref} className={containerCls} style={style}>

    </div>
  );
}
  • 其中componentConfig是从ConfigProvider上传下来的组件全局配置,可以配置所有组件的参数,但它的优先级是高于defaultProps,也就是componentConfig?.Empty的属性如果有和defaultProps同名的,componentConfig?.Empty会覆盖defaultProps
  • baseProps是直接传给Empty组件的props,优先级最高
  • 最低优先级的是defaultProps

参数:

  • componentProps: PropsType,必填,传入的组件props。
  • defaultProps: Partial,必填,组件的默认props。
  • globalComponentConfig: Partial | undefined,可选,全局组件配置。

返回值

合并后的最终props

useMergeValue

参考了arco.design的设计。

组件有时分为受控组件和非受控组件,如果可以统一处理受控和非受控的逻辑,我们希望当你传入value的时候自动识别为受控状态,当没有传入value或者传入了defaultValue,我们认为是非受控的状态。

对外暴露的都是最终的值和改变值的方法。

参数

useMergeValue 接受两个参数:

  • defaultStateValue(必需)- 组件初始状态的默认值。
  • props(可选)- 一个包含 defaultValue 和 value 两个属性的对象,用于控制组件状态。
    • defaultValue - 组件默认状态的值。
    • value - 控制组件状态的值。

返回值

  • mergedValue - 组件状态的合并值。
  • setStateValue - 用于更新组件状态的函数。
  • stateValue - 组件当前状态的值。

案例

如下,这是一个checkbox组件

import React, { useContext, useCallback, useRef, useEffect } from 'react';
import useMergeValue from 'xx';

function Checkbox<T extends React.ReactText>(baseProps: CheckboxProps<T>, ref) {
  const [checked, setChecked] = useMergeValue(false, {
    value: props.checked,
    defaultValue: props.defaultChecked,
  });

  // ...
}

Checkbox.displayName = 'Checkbox';

假如外部传入了props.checked,那么这个checkbox是一个受控组件,只有props.checked变化的时候,checkbox的状态才会变化。

如果没有传props.checked,而是传入了props.defaultChecked,那么这个checkbox是一个非受控组件,比如你点击checkbox这个组件的时候,会根据你点击的情况自动切换是否是check状态

源码解析

如下,首先先检测value,也就是受控的属性value是否有值,有的话,说明是受控状态,所以返回给外部的就是受控的值value

  const mergedValue = isUndefined(value) ? stateValue : value;
  return [mergedValue, ...]

如果是非受控状态,如下:

  const [stateValue, setStateValue] = useState<T>(
    // eslint-disable-next-line no-nested-ternary
    !isUndefined(value) ? value : !isUndefined(defaultValue) ? defaultValue : defaultStateValue
  );

此时stateValue就是非受控状态了,const mergedValue = isUndefined(value) ? stateValue : value;这里就会返回非受控状态的值。

最后,我们以防万一,有可能刚开始是有value的,也就是处于受控状态,然后将value属性删除,变为了非受控状态:

  useEffect(() => {
    if (firstRenderRef.current) {
      firstRenderRef.current = false;
      return;
    }

    if (value === undefined) {
      setStateValue(value);
    }
  }, [value]);

当然,这个函数并不是完美的,比如我初始化受控状态的值就是undefined,也就是value就是undefined的时候就会出问题,但是这个hook是供我们组件库内部使用,所以我们自己知道不会出现这种状况。