refun
Version:
A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:
38 lines (32 loc) • 1.85 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import { useState, useRef } from 'react';
import { EMPTY_OBJECT } from 'tsfn';
import { shallowEqualByKeys } from './utils';
export var mapState = function mapState(stateName, stateSetterName, getValue, watchKeys) {
return function (props) {
var _Object$assign;
var prevProps = useRef(EMPTY_OBJECT);
var _useState = useState(prevProps.current === EMPTY_OBJECT ? getValue(props) : EMPTY_OBJECT),
_useState2 = _slicedToArray(_useState, 2),
state = _useState2[0],
setState = _useState2[1];
var nextState = state;
if (prevProps.current !== EMPTY_OBJECT && !shallowEqualByKeys(prevProps.current, props, watchKeys)) {
// React will continue current render, delivering 'state', which is already old state.
// By assigning to 'nextState', we deliver fresh state during current render.
// After that React will rerender due to actual 'setState', delivering same state value.
nextState = getValue(props); // React prevents rerender by setState if next value is the same as current state.
// But in this case, setState is triggered during the render phase.
// React does not interrupt render, and lets the component to render till the end,
// and after that initiates next render caused by this setState.
// Manually checking for equality to prevent unnecessary rerender.
if (nextState !== state) {
setState(nextState);
}
}
prevProps.current = props;
return Object.assign({}, props, (_Object$assign = {}, _defineProperty(_Object$assign, stateName, nextState), _defineProperty(_Object$assign, stateSetterName, setState), _Object$assign));
};
};
//# sourceMappingURL=map-state.js.map