@orca-fe/hooks
Version:
React Hooks Collections
91 lines (87 loc) • 3.36 kB
JavaScript
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];
}