UNPKG

@orca-fe/hooks

Version:

React Hooks Collections

91 lines (87 loc) 3.36 kB
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import { useState } from 'react'; import { isUndefined, omit, omitBy, pick } from 'lodash-es'; import useMemoizedFn from "./useMemorizedFn"; export var upperFirstKey = (str = '') => { if (str.length > 0) { return str[0].toUpperCase() + str.substr(1); } return ''; }; export var getPropListenerName = key => `on${key === 'value' ? '' : upperFirstKey(key)}Change`; export var getPropsListenerName = (props = {}) => Object.keys(props).map(getPropListenerName); export var validateProps = (initProps, newProps = {}) => { var res = {}; Object.keys(newProps).forEach(key => { if (Object.hasOwnProperty.call(initProps, key)) { res[key] = newProps[key]; } }); return res; }; /** * 对比变化的属性,提取出需要变化的state(属性值为undefined) * * @param newProps * @private */ export var getChangedState = (props, newProps = {}) => { var res; Object.keys(newProps).forEach(key => { if (props[key] === undefined) { if (!res) res = {}; res[key] = newProps[key]; } }); return res; }; export default function useControllableProps(props, initProps = {}, config = {}) { var _config$omitListener = config.omitListener, omitListener = _config$omitListener === void 0 ? true : _config$omitListener, _config$autoOnChange = config.autoOnChange, autoOnChange = _config$autoOnChange === void 0 ? true : _config$autoOnChange, _config$combineListen = config.combineListener, combineListener = _config$combineListen === void 0 ? true : _config$combineListen; var _useState = useState(() => Object.keys(initProps)), _useState2 = _slicedToArray(_useState, 1), initPropsKeys = _useState2[0]; // inner state var _useState3 = useState(initProps), _useState4 = _slicedToArray(_useState3, 2), state = _useState4[0], setState = _useState4[1]; var finalProps = _objectSpread(_objectSpread({}, state), omitBy(props, isUndefined)); // final state var mergedState = pick(finalProps, initPropsKeys); var changeProps = useMemoizedFn((newProps = {}) => { var onPropsChange = props.onPropsChange; // delete attrs which not in `initProps` var validProps = validateProps(initProps, newProps); var nextState = getChangedState(props, validProps); if (nextState) { setState(_objectSpread(_objectSpread({}, mergedState), nextState)); } var result = {}; if (autoOnChange) { Object.keys(validProps).forEach(key => { var listenerName = getPropListenerName(key); var onChangeFunc = props[listenerName]; if (typeof onChangeFunc === 'function') { result[key] = onChangeFunc(validProps[key], newProps); } }); } if (combineListener && typeof onPropsChange === 'function') { result.default = onPropsChange(_objectSpread(_objectSpread({}, mergedState), newProps)); } return result; }); if (omitListener) { // get the listener prop name according `initProps` var omitProps = [].concat(combineListener ? ['onPropsChange'] : []).concat(autoOnChange ? getPropsListenerName(initProps) : []); // remove all listener finalProps = omit(finalProps, omitProps); } return [finalProps, changeProps]; }