react hook 组件默认值

import { useState, useRef, SyntheticEvent } from 'react';

/**
 * 表单受控组件中,输入输出的统一规范
 *
 * - `value` 用于输入组件当前值
 * - `onChange` 用于回调组件最新值
 */
export interface ControlledProps<
  V,
  E extends SyntheticEvent = SyntheticEvent,
  C extends ChangeContext<E> = ChangeContext<E>
> {
  /**
   * 未提供 `value` 的情况下,提供了 `defaultValue`,则可以当做是非受控组件使用
   */
  defaultValue?: V;

  /**
   * 当前值
   */
  value?: V;

  /**
   * 值发生变更时进行回调
   * - `value` 变更的目标值
   * - `context` 此次变更的更多上下文信息,其中 `context.event` 可以获得导致变更的 React 事件
   */
  onChange?(value: V, context: C): void;
}

/**
 * 表单 `onChange` 事件中,提供的上下文信息
 */
export interface ChangeContext<E extends SyntheticEvent = SyntheticEvent> {
  /**
   * 触发 `onChange` 事件的事件对象
   */
  event: E;
}

const noop = () => {};


export interface ChangeHandler<T, P extends any[]> {
  (value: T, ...args: P): any;
}

export function useDefault<T, P extends any[]>(
  value: T,
  defaultValue: T,
  onChange: ChangeHandler<T, P>,
): [T, ChangeHandler<T, P>] {
  const isControlledRef = useRef<boolean>(false);
  const [internalValue, setInternalValue] = useState(defaultValue);

  // 受控模式
  if (isControlledRef.current || typeof value !== 'undefined') {
    isControlledRef.current = true;
    return [value, onChange || noop];
  }

  // 非受控模式
  return [
    internalValue,
    (newValue, ...args) => {
      setInternalValue(newValue);
      if (typeof onChange === 'function') {
        onChange(newValue, ...args);
      }
    },
  ];
}

export function useDefaultValue<T, P extends ControlledProps<T>>(
  props: P,
  defaultDefaultValue?: T,
) {
  //   type ReturnType = Omit<P, 'defaultValue'>;

  const { defaultValue, value, onChange = noop, ...restProps } = props;

  const [finalValue, finalOnChange] = useDefault(
    value as T,
    typeof defaultValue === 'undefined' ? (defaultDefaultValue as T) : defaultValue,
    onChange,
  );

  return {
    value: finalValue,
    onChange: finalOnChange,
    ...restProps,
  } as any;
}

使用:

function Demo(props: DemoProps) {
  const { className, value, onChange, style, ...rest } = useDefaultValue(props, '');
  return <div></div>
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值