You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
4.8 KiB

"use strict";
exports.__esModule = true;
exports.createSelectorHook = createSelectorHook;
exports.useSelector = exports.initializeUseSelector = void 0;
var _react = require("react");
var _useReduxContext = require("./useReduxContext");
var _Context = require("../components/Context");
var _useSyncExternalStore = require("../utils/useSyncExternalStore");
let useSyncExternalStoreWithSelector = _useSyncExternalStore.notInitialized;
const initializeUseSelector = fn => {
useSyncExternalStoreWithSelector = fn;
};
exports.initializeUseSelector = initializeUseSelector;
const refEquality = (a, b) => a === b;
/**
* Hook factory, which creates a `useSelector` hook bound to a given context.
*
* @param {React.Context} [context=ReactReduxContext] Context passed to your `<Provider>`.
* @returns {Function} A `useSelector` hook bound to the specified context.
*/
function createSelectorHook(context = _Context.ReactReduxContext) {
const useReduxContext = context === _Context.ReactReduxContext ? _useReduxContext.useReduxContext : (0, _useReduxContext.createReduxContextHook)(context);
return function useSelector(selector, equalityFnOrOptions = {}) {
const {
equalityFn = refEquality,
stabilityCheck = undefined,
noopCheck = undefined
} = typeof equalityFnOrOptions === 'function' ? {
equalityFn: equalityFnOrOptions
} : equalityFnOrOptions;
if (process.env.NODE_ENV !== 'production') {
if (!selector) {
throw new Error(`You must pass a selector to useSelector`);
}
if (typeof selector !== 'function') {
throw new Error(`You must pass a function as a selector to useSelector`);
}
if (typeof equalityFn !== 'function') {
throw new Error(`You must pass a function as an equality function to useSelector`);
}
}
const {
store,
subscription,
getServerState,
stabilityCheck: globalStabilityCheck,
noopCheck: globalNoopCheck
} = useReduxContext();
const firstRun = (0, _react.useRef)(true);
const wrappedSelector = (0, _react.useCallback)({
[selector.name](state) {
const selected = selector(state);
if (process.env.NODE_ENV !== 'production') {
const finalStabilityCheck = typeof stabilityCheck === 'undefined' ? globalStabilityCheck : stabilityCheck;
if (finalStabilityCheck === 'always' || finalStabilityCheck === 'once' && firstRun.current) {
const toCompare = selector(state);
if (!equalityFn(selected, toCompare)) {
console.warn('Selector ' + (selector.name || 'unknown') + ' returned a different result when called with the same parameters. This can lead to unnecessary rerenders.' + '\nSelectors that return a new reference (such as an object or an array) should be memoized: https://redux.js.org/usage/deriving-data-selectors#optimizing-selectors-with-memoization', {
state,
selected,
selected2: toCompare
});
}
}
const finalNoopCheck = typeof noopCheck === 'undefined' ? globalNoopCheck : noopCheck;
if (finalNoopCheck === 'always' || finalNoopCheck === 'once' && firstRun.current) {
// @ts-ignore
if (selected === state) {
console.warn('Selector ' + (selector.name || 'unknown') + ' returned the root state when called. This can lead to unnecessary rerenders.' + '\nSelectors that return the entire state are almost certainly a mistake, as they will cause a rerender whenever *anything* in state changes.');
}
}
if (firstRun.current) firstRun.current = false;
}
return selected;
}
}[selector.name], [selector, globalStabilityCheck, stabilityCheck]);
const selectedState = useSyncExternalStoreWithSelector(subscription.addNestedSub, store.getState, getServerState || store.getState, wrappedSelector, equalityFn);
(0, _react.useDebugValue)(selectedState);
return selectedState;
};
}
/**
* A hook to access the redux store's state. This hook takes a selector function
* as an argument. The selector is called with the store state.
*
* This hook takes an optional equality comparison function as the second parameter
* that allows you to customize the way the selected state is compared to determine
* whether the component needs to be re-rendered.
*
* @param {Function} selector the selector function
* @param {Function=} equalityFn the function that will be used to determine equality
*
* @returns {any} the selected state
*
* @example
*
* import React from 'react'
* import { useSelector } from 'react-redux'
*
* export const CounterComponent = () => {
* const counter = useSelector(state => state.counter)
* return <div>{counter}</div>
* }
*/
const useSelector = /*#__PURE__*/createSelectorHook();
exports.useSelector = useSelector;