-
Notifications
You must be signed in to change notification settings - Fork 664
Add warning in development when a result function is x => x.
#645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+1,168
−757
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
6cf53cb
Add initial implementation for `noopCheck`
aryaemami59 a8645a0
Disable no-op check for some unit tests
aryaemami59 703bf3a
Disable no-op check for performance tests
aryaemami59 1615733
Rename `StabilityCheckFrequency` to `DevModeCheckFrequency`
aryaemami59 cdc93c0
Rename `noopCheck` to `identityFunctionCheck`
aryaemami59 b25c9c9
Add JSDocs for `runIdentityFunctionCheck` utility function.
aryaemami59 ac4da4a
Update `README` to include `identityFunctionCheck`
aryaemami59 5a53b42
Add JSDocs for `setGlobalIdentityFunctionCheck`
aryaemami59 751daf3
Add JSDocs for `CreateSelectorOptions.identityFunctionCheck`
aryaemami59 611d833
Add `identityFunctionCheck` to v5 summary in `README`
aryaemami59 c2563d3
Fix copy-paste error in `README`
aryaemami59 45f036a
Fix JSDocs for `shouldRunDevModeCheck`
aryaemami59 c05bcc5
Fix issue with `firstRun`
aryaemami59 3a51095
Add `DevModeChecks`
aryaemami59 397f3d8
Update `README` with new dev-mode-check API
aryaemami59 dda015b
Fix `inputStabilityCheck` warning message.
aryaemami59 df84098
export `setGlobalDevModeChecks` in `index.ts`
aryaemami59 17718f3
Remove '@internal' imports
aryaemami59 4952ad4
Fix `devModeChecks` in type tests
aryaemami59 20a7d97
increase performance timer from 1000 to 1500
aryaemami59 bc7a188
Change package version as a workaround
aryaemami59 01792bc
Silence test logging
markerikson 6f3bd23
Fix lockfile issue
markerikson ae0a921
Fix silly types import issue
markerikson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import type { AnyFunction } from '../types' | ||
|
|
||
| /** | ||
| * Runs a check to determine if the given result function behaves as an | ||
| * identity function. An identity function is one that returns its | ||
| * input unchanged, for example, `x => x`. This check helps ensure | ||
| * efficient memoization and prevent unnecessary re-renders by encouraging | ||
| * proper use of transformation logic in result functions and | ||
| * extraction logic in input selectors. | ||
| * | ||
| * @param resultFunc - The result function to be checked. | ||
| */ | ||
| export const runIdentityFunctionCheck = (resultFunc: AnyFunction) => { | ||
| let isInputSameAsOutput = false | ||
| try { | ||
| const emptyObject = {} | ||
| if (resultFunc(emptyObject) === emptyObject) isInputSameAsOutput = true | ||
| } catch { | ||
| // Do nothing | ||
| } | ||
| if (isInputSameAsOutput) { | ||
| console.warn( | ||
| 'The result function returned its own inputs without modification. e.g' + | ||
| '\n`createSelector([state => state.todos], todos => todos)`' + | ||
| '\nThis could lead to inefficient memoization and unnecessary re-renders.' + | ||
| '\nEnsure transformation logic is in the result function, and extraction logic is in the input selectors.' | ||
| ) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| import type { CreateSelectorOptions, UnknownMemoizer } from '../types' | ||
|
|
||
| /** | ||
| * Runs a stability check to ensure the input selector results remain stable | ||
| * when provided with the same arguments. This function is designed to detect | ||
| * changes in the output of input selectors, which can impact the performance of memoized selectors. | ||
| * | ||
| * @param inputSelectorResultsObject - An object containing two arrays: `inputSelectorResults` and `inputSelectorResultsCopy`, representing the results of input selectors. | ||
| * @param options - Options object consisting of a `memoize` function and a `memoizeOptions` object. | ||
| * @param inputSelectorArgs - List of arguments being passed to the input selectors. | ||
| */ | ||
| export const runInputStabilityCheck = ( | ||
| inputSelectorResultsObject: { | ||
| inputSelectorResults: unknown[] | ||
| inputSelectorResultsCopy: unknown[] | ||
| }, | ||
| options: Required< | ||
| Pick< | ||
| CreateSelectorOptions<UnknownMemoizer, UnknownMemoizer>, | ||
| 'memoize' | 'memoizeOptions' | ||
| > | ||
| >, | ||
| inputSelectorArgs: unknown[] | IArguments | ||
| ) => { | ||
| const { memoize, memoizeOptions } = options | ||
| const { inputSelectorResults, inputSelectorResultsCopy } = | ||
| inputSelectorResultsObject | ||
| const createAnEmptyObject = memoize(() => ({}), ...memoizeOptions) | ||
| // if the memoize method thinks the parameters are equal, these *should* be the same reference | ||
| const areInputSelectorResultsEqual = | ||
| createAnEmptyObject.apply(null, inputSelectorResults) === | ||
| createAnEmptyObject.apply(null, inputSelectorResultsCopy) | ||
| if (!areInputSelectorResultsEqual) { | ||
| // do we want to log more information about the selector? | ||
| console.warn( | ||
| 'An input selector returned a different result when passed same arguments.' + | ||
| '\nThis means your output selector will likely run more frequently than intended.' + | ||
| '\nAvoid returning a new reference inside your input selector, e.g.' + | ||
| '\n`createSelector([state => state.todos.map(todo => todo.id)], todoIds => todoIds.length)`', | ||
| { | ||
| arguments: inputSelectorArgs, | ||
| firstInputs: inputSelectorResults, | ||
| secondInputs: inputSelectorResultsCopy | ||
| } | ||
| ) | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.