react-with-hoc
Version:
Work with React and HOCs (Higher-Order Components)
63 lines (62 loc) • 10.2 kB
JavaScript
import React, { useState } from "react";
import { newHoc } from "../utils/newHoc";
function noop() {}
/**
* like `useState` or you can pass properties to the component to make it controllable
* @example
* const CounterWithState = withState("count", { init: 0 })(function Counter({count, setCount}: {count: number; setCount: Dispatch<SetStateAction<number>>}) {
* return <button onClick={() => setCount(count + 1)}>{count}</button>;
* });
* // using CounterWithState as self controlled
* function IndependentCounters() {
* return <>
* <CounterWithState />
* <CounterWithState />
* </>;
* }
* <IndependentCounters /> // will render 2 buttons that can count independently
*
* // using CounterWithState as parent controlled
* function SameCounters() {
* const [count, setCount] = useState(0);
* return <>
* <CounterWithState count={count} setCount={setCount} />
* <CounterWithState count={count} setCount={setCount} />
* </>;
* }
* <SameCounters /> // will render 2 buttons with the same count
*/
export const withState = newHoc(function withState(Component, stateName, {
init,
setterName = "set" + stateName.charAt(0).toUpperCase() + stateName.slice(1)
} = {}) {
let locallyControlled;
function getUseState(props) {
if (process.env.NODE_ENV !== "production" && locallyControlled !== undefined) {
if (locallyControlled) {
if (stateName in props || setterName in props) {
throw new Error(`The state "${stateName}" was locally controlled and then it changed`);
}
} else {
if (!(stateName in props)) {
throw new Error(`The state "${stateName}" was controlled by its parent and then it changed`);
}
}
}
locallyControlled = !(stateName in props || setterName in props);
if (locallyControlled === true) {
return useState(typeof init === "function" ? init(props) : init);
}
return [props[stateName], props[setterName] ?? noop];
}
return function WithState(props) {
const [state, setState] = getUseState(props);
return /*#__PURE__*/React.createElement(Component, {
[stateName]: state,
[setterName]: setState,
...props
});
};
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsInVzZVN0YXRlIiwibmV3SG9jIiwibm9vcCIsIndpdGhTdGF0ZSIsIkNvbXBvbmVudCIsInN0YXRlTmFtZSIsImluaXQiLCJzZXR0ZXJOYW1lIiwiY2hhckF0IiwidG9VcHBlckNhc2UiLCJzbGljZSIsImxvY2FsbHlDb250cm9sbGVkIiwiZ2V0VXNlU3RhdGUiLCJwcm9wcyIsInByb2Nlc3MiLCJlbnYiLCJOT0RFX0VOViIsInVuZGVmaW5lZCIsIkVycm9yIiwiV2l0aFN0YXRlIiwic3RhdGUiLCJzZXRTdGF0ZSIsImNyZWF0ZUVsZW1lbnQiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaG9jcy93aXRoU3RhdGUudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCwgeyBDb21wb25lbnRUeXBlLCBGdW5jdGlvbkNvbXBvbmVudCwgdXNlU3RhdGUgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IEZuLCBJbnRlcnNlY3Rpb25GbiwgUGlwZSwgU2V0T3B0aW9uYWxGbiwgVG9TY2hlbWEgfSBmcm9tIFwiLi4vdHlwZXMvRm5cIjtcbmltcG9ydCB7IEhvYyB9IGZyb20gXCIuLi90eXBlcy9Ib2NcIjtcbmltcG9ydCB7IG5ld0hvYyB9IGZyb20gXCIuLi91dGlscy9uZXdIb2NcIjtcblxuaW50ZXJmYWNlIFdpdGhTdGF0ZUZuPFxuICBQcm9wVmFsdWUsXG4gIFN0YXRlTmFtZSBleHRlbmRzIHN0cmluZyxcbiAgU2V0dGVyTmFtZSBleHRlbmRzIHN0cmluZyxcbiAgUHJvcHNTY2hlbWEgZXh0ZW5kcyBbc3RyaW5nIHwgbnVtYmVyIHwgc3ltYm9sLCBhbnldLFxuPiBleHRlbmRzIEZuIHtcbiAgcmV0dXJuOiBQaXBlPFxuICAgIHRoaXNbXCJhcmcwXCJdLFxuICAgIFtcbiAgICAgIEludGVyc2VjdGlvbkZuPFxuICAgICAgICB8IFtTdGF0ZU5hbWUsIFByb3BWYWx1ZV1cbiAgICAgICAgfCBbU2V0dGVyTmFtZSwgUmVhY3QuRGlzcGF0Y2g8UmVhY3QuU2V0U3RhdGVBY3Rpb248UHJvcFZhbHVlPj5dXG4gICAgICA+LFxuICAgICAgU2V0T3B0aW9uYWxGbjxTdGF0ZU5hbWUgfCBTZXR0ZXJOYW1lPixcbiAgICAgIEludGVyc2VjdGlvbkZuPFByb3BzU2NoZW1hPixcbiAgICBdXG4gID47XG59XG5cbnR5cGUgV2l0aFN0YXRlSG9jID0gPFxuICBQcm9wVmFsdWUsXG4gIFN0YXRlTmFtZSBleHRlbmRzIHN0cmluZyxcbiAgU2V0dGVyTmFtZSBleHRlbmRzIHN0cmluZyA9IGBzZXQke0NhcGl0YWxpemU8U3RhdGVOYW1lPn1gLFxuICBQcm9wcyBleHRlbmRzIG9iamVjdCA9IHt9LFxuPihcbiAgc3RhdGVOYW1lOiBTdGF0ZU5hbWUsXG4gIG9wdGlvbnM/OiB7XG4gICAgLyoqXG4gICAgICogdGhlIGluaXRpYWwgdmFsdWVcbiAgICAgKlxuICAgICAqICBAZXhhbXBsZVxuICAgICAqIC8vIGluaXRpYWwgc3RhdGUgZnJvbSBhIGNvbnN0YW50XG4gICAgICoge2luaXQ6IFwiaW5pdGlhbCB2YWx1ZVwifVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiAvLyBpbml0aWFsIHN0YXRlIHdpbGwgYmUgZGVyaXZlZCBmcm9tIHNvbWVQcm9wXG4gICAgICoge2luaXQ6ICh7IHNvbWVQcm9wIH06IHtzb21lUHJvcDogbnVtYmVyfSkgPT4gc29tZVByb3AgKyAxfVxuICAgICAqL1xuICAgIGluaXQ/OiBFeGNsdWRlPFByb3BWYWx1ZSwgRnVuY3Rpb24+IHwgKChwcm9wczogUHJvcHMpID0+IFByb3BWYWx1ZSk7XG4gICAgLyoqXG4gICAgICogdGhlIHNldHRlcidzIG5hbWUgcHJvcGVydHksIHVzdWFsbHkgeW91IHdhbnQgdG8gdGhlIGRlZmF1bHQgd2hpY2ggaXMgYHNldCR7Q2FwaXRhbGl6ZTxTdGF0ZU5hbWU+fWBcbiAgICAgKiBAZGVmYXVsdCBgc2V0JHtDYXBpdGFsaXplPFN0YXRlTmFtZT59YFxuICAgICAqIEBleGFtcGxlXG4gICAgICogd2l0aFN0YXRlKFwic29tZVN0YXRlXCIsIHtcbiAgICAgKiAgIGluaXQ6IDAsXG4gICAgICogICBzZXR0ZXJOYW1lOiBcInNldFNvbWVTdGF0ZVwiIC8vIGRlZmF1bHRcbiAgICAgKiB9KShFeGFtcGxlKVxuICAgICAqL1xuICAgIHNldHRlck5hbWU/OiBTZXR0ZXJOYW1lO1xuICB9LFxuKSA9PiBIb2M8W1dpdGhTdGF0ZUZuPFByb3BWYWx1ZSwgU3RhdGVOYW1lLCBTZXR0ZXJOYW1lLCBUb1NjaGVtYTxQcm9wcz4+XT47XG5cbmZ1bmN0aW9uIG5vb3AoKTogdm9pZCB7fVxuXG4vKipcbiAqIGxpa2UgYHVzZVN0YXRlYCBvciB5b3UgY2FuIHBhc3MgcHJvcGVydGllcyB0byB0aGUgY29tcG9uZW50IHRvIG1ha2UgaXQgY29udHJvbGxhYmxlXG4gKiBAZXhhbXBsZVxuICogY29uc3QgQ291bnRlcldpdGhTdGF0ZSA9IHdpdGhTdGF0ZShcImNvdW50XCIsIHsgaW5pdDogMCB9KShmdW5jdGlvbiBDb3VudGVyKHtjb3VudCwgc2V0Q291bnR9OiB7Y291bnQ6IG51bWJlcjsgc2V0Q291bnQ6IERpc3BhdGNoPFNldFN0YXRlQWN0aW9uPG51bWJlcj4+fSkge1xuICogICByZXR1cm4gPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiBzZXRDb3VudChjb3VudCArIDEpfT57Y291bnR9PC9idXR0b24+O1xuICogfSk7XG4gKiAvLyB1c2luZyBDb3VudGVyV2l0aFN0YXRlIGFzIHNlbGYgY29udHJvbGxlZFxuICogZnVuY3Rpb24gSW5kZXBlbmRlbnRDb3VudGVycygpIHtcbiAqICAgcmV0dXJuIDw+XG4gKiAgICAgPENvdW50ZXJXaXRoU3RhdGUgLz5cbiAqICAgICA8Q291bnRlcldpdGhTdGF0ZSAvPlxuICogICA8Lz47XG4gKiB9XG4gKiA8SW5kZXBlbmRlbnRDb3VudGVycyAvPiAvLyB3aWxsIHJlbmRlciAyIGJ1dHRvbnMgdGhhdCBjYW4gY291bnQgaW5kZXBlbmRlbnRseVxuICpcbiAqIC8vIHVzaW5nIENvdW50ZXJXaXRoU3RhdGUgYXMgcGFyZW50IGNvbnRyb2xsZWRcbiAqIGZ1bmN0aW9uIFNhbWVDb3VudGVycygpIHtcbiAqICAgY29uc3QgW2NvdW50LCBzZXRDb3VudF0gPSB1c2VTdGF0ZSgwKTtcbiAqICAgcmV0dXJuIDw+XG4gKiAgICAgPENvdW50ZXJXaXRoU3RhdGUgY291bnQ9e2NvdW50fSBzZXRDb3VudD17c2V0Q291bnR9IC8+XG4gKiAgICAgPENvdW50ZXJXaXRoU3RhdGUgY291bnQ9e2NvdW50fSBzZXRDb3VudD17c2V0Q291bnR9IC8+XG4gKiAgIDwvPjtcbiAqIH1cbiAqIDxTYW1lQ291bnRlcnMgLz4gLy8gd2lsbCByZW5kZXIgMiBidXR0b25zIHdpdGggdGhlIHNhbWUgY291bnRcbiAqL1xuZXhwb3J0IGNvbnN0IHdpdGhTdGF0ZSA9IG5ld0hvYzxXaXRoU3RhdGVIb2M+KGZ1bmN0aW9uIHdpdGhTdGF0ZShcbiAgQ29tcG9uZW50OiBDb21wb25lbnRUeXBlLFxuICBzdGF0ZU5hbWU6IHN0cmluZyxcbiAge1xuICAgIGluaXQsXG4gICAgc2V0dGVyTmFtZSA9IFwic2V0XCIgKyBzdGF0ZU5hbWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdGF0ZU5hbWUuc2xpY2UoMSksXG4gIH06IGFueSA9IHt9LFxuKTogRnVuY3Rpb25Db21wb25lbnQge1xuICBsZXQgbG9jYWxseUNvbnRyb2xsZWQ6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gIGZ1bmN0aW9uIGdldFVzZVN0YXRlKHByb3BzOiBhbnkpOiBhbnkge1xuICAgIGlmIChcbiAgICAgIHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSBcInByb2R1Y3Rpb25cIiAmJlxuICAgICAgbG9jYWxseUNvbnRyb2xsZWQgIT09IHVuZGVmaW5lZFxuICAgICkge1xuICAgICAgaWYgKGxvY2FsbHlDb250cm9sbGVkKSB7XG4gICAgICAgIGlmIChzdGF0ZU5hbWUgaW4gcHJvcHMgfHwgc2V0dGVyTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBUaGUgc3RhdGUgXCIke3N0YXRlTmFtZX1cIiB3YXMgbG9jYWxseSBjb250cm9sbGVkIGFuZCB0aGVuIGl0IGNoYW5nZWRgLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICghKHN0YXRlTmFtZSBpbiBwcm9wcykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgVGhlIHN0YXRlIFwiJHtzdGF0ZU5hbWV9XCIgd2FzIGNvbnRyb2xsZWQgYnkgaXRzIHBhcmVudCBhbmQgdGhlbiBpdCBjaGFuZ2VkYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgbG9jYWxseUNvbnRyb2xsZWQgPSAhKHN0YXRlTmFtZSBpbiBwcm9wcyB8fCBzZXR0ZXJOYW1lIGluIHByb3BzKTtcbiAgICBpZiAobG9jYWxseUNvbnRyb2xsZWQgPT09IHRydWUpIHtcbiAgICAgIHJldHVybiB1c2VTdGF0ZSh0eXBlb2YgaW5pdCA9PT0gXCJmdW5jdGlvblwiID8gaW5pdChwcm9wcykgOiBpbml0KTtcbiAgICB9XG4gICAgcmV0dXJuIFtwcm9wc1tzdGF0ZU5hbWVdLCBwcm9wc1tzZXR0ZXJOYW1lXSA/PyBub29wXTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiBXaXRoU3RhdGUocHJvcHM6IGFueSk6IEpTWC5FbGVtZW50IHtcbiAgICBjb25zdCBbc3RhdGUsIHNldFN0YXRlXSA9IGdldFVzZVN0YXRlKHByb3BzKTtcblxuICAgIHJldHVybiAoXG4gICAgICA8Q29tcG9uZW50XG4gICAgICAgIHsuLi57XG4gICAgICAgICAgW3N0YXRlTmFtZV06IHN0YXRlLFxuICAgICAgICAgIFtzZXR0ZXJOYW1lXTogc2V0U3RhdGUsXG4gICAgICAgIH19XG4gICAgICAgIHsuLi5wcm9wc31cbiAgICAgIC8+XG4gICAgKTtcbiAgfTtcbn0pO1xuIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxLQUFLLElBQXNDQyxRQUFRLFFBQVEsT0FBTztBQUd6RSxTQUFTQyxNQUFNLFFBQVEsaUJBQWlCO0FBc0R4QyxTQUFTQyxJQUFJQSxDQUFBLEVBQVMsQ0FBQzs7QUFFdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLE1BQU1DLFNBQVMsR0FBR0YsTUFBTSxDQUFlLFNBQVNFLFNBQVNBLENBQzlEQyxTQUF3QixFQUN4QkMsU0FBaUIsRUFDakI7RUFDRUMsSUFBSTtFQUNKQyxVQUFVLEdBQUcsS0FBSyxHQUFHRixTQUFTLENBQUNHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQ0MsV0FBVyxDQUFDLENBQUMsR0FBR0osU0FBUyxDQUFDSyxLQUFLLENBQUMsQ0FBQztBQUN2RSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQ1E7RUFDbkIsSUFBSUMsaUJBQXNDO0VBQzFDLFNBQVNDLFdBQVdBLENBQUNDLEtBQVUsRUFBTztJQUNwQyxJQUNFQyxPQUFPLENBQUNDLEdBQUcsQ0FBQ0MsUUFBUSxLQUFLLFlBQVksSUFDckNMLGlCQUFpQixLQUFLTSxTQUFTLEVBQy9CO01BQ0EsSUFBSU4saUJBQWlCLEVBQUU7UUFDckIsSUFBSU4sU0FBUyxJQUFJUSxLQUFLLElBQUlOLFVBQVUsSUFBSU0sS0FBSyxFQUFFO1VBQzdDLE1BQU0sSUFBSUssS0FBSyxDQUNaLGNBQWFiLFNBQVUsOENBQzFCLENBQUM7UUFDSDtNQUNGLENBQUMsTUFBTTtRQUNMLElBQUksRUFBRUEsU0FBUyxJQUFJUSxLQUFLLENBQUMsRUFBRTtVQUN6QixNQUFNLElBQUlLLEtBQUssQ0FDWixjQUFhYixTQUFVLG9EQUMxQixDQUFDO1FBQ0g7TUFDRjtJQUNGO0lBRUFNLGlCQUFpQixHQUFHLEVBQUVOLFNBQVMsSUFBSVEsS0FBSyxJQUFJTixVQUFVLElBQUlNLEtBQUssQ0FBQztJQUNoRSxJQUFJRixpQkFBaUIsS0FBSyxJQUFJLEVBQUU7TUFDOUIsT0FBT1gsUUFBUSxDQUFDLE9BQU9NLElBQUksS0FBSyxVQUFVLEdBQUdBLElBQUksQ0FBQ08sS0FBSyxDQUFDLEdBQUdQLElBQUksQ0FBQztJQUNsRTtJQUNBLE9BQU8sQ0FBQ08sS0FBSyxDQUFDUixTQUFTLENBQUMsRUFBRVEsS0FBSyxDQUFDTixVQUFVLENBQUMsSUFBSUwsSUFBSSxDQUFDO0VBQ3REO0VBRUEsT0FBTyxTQUFTaUIsU0FBU0EsQ0FBQ04sS0FBVSxFQUFlO0lBQ2pELE1BQU0sQ0FBQ08sS0FBSyxFQUFFQyxRQUFRLENBQUMsR0FBR1QsV0FBVyxDQUFDQyxLQUFLLENBQUM7SUFFNUMsb0JBQ0VkLEtBQUEsQ0FBQXVCLGFBQUEsQ0FBQ2xCLFNBQVM7TUFFTixDQUFDQyxTQUFTLEdBQUdlLEtBQUs7TUFDbEIsQ0FBQ2IsVUFBVSxHQUFHYyxRQUFRO01BQUEsR0FFcEJSO0lBQUssQ0FDVixDQUFDO0VBRU4sQ0FBQztBQUNILENBQUMsQ0FBQyJ9
//# sourceMappingURL=withState.js.map