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.
		
		
		
		
		
			
		
			
				
					122 lines
				
				4.5 KiB
			
		
		
			
		
	
	
					122 lines
				
				4.5 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								# useMemoOne
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[`useMemo`](https://reactjs.org/docs/hooks-reference.html#usememo) and [`useCallback`](https://reactjs.org/docs/hooks-reference.html#usecallback) with a stable cache (semantic guarantee)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[](https://github.com/alexreardon/use-memo-one/workflows/Validate/badge.svg)
							 | 
						||
| 
								 | 
							
								[](https://www.npmjs.com/package/use-memo-one)
							 | 
						||
| 
								 | 
							
								[](https://david-dm.org/alexreardon/use-memo-one)
							 | 
						||
| 
								 | 
							
								[](https://bundlephobia.com/result?p=use-memo-one)
							 | 
						||
| 
								 | 
							
								[](https://bundlephobia.com/result?p=use-memo-one)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Background
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`useMemo` and `useCallback` cache the most recent result. However, this cache can be destroyed by `React` when it wants to:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								> You may rely on useMemo as a performance optimization, **not as a semantic guarantee**. In the future, **React may choose to “forget” some previously memoized values** and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo — and then add it to optimize performance. [- React docs](https://reactjs.org/docs/hooks-reference.html#usememo)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`useMemoOne` and `useCallbackOne` are `concurrent mode` safe alternatives to `useMemo` and `useCallback` **that do provide semantic guarantee**. What this means is that you will always get the same reference for a memoized value so long as there is no input change.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Using `useMemoOne` and `useCallbackOne` will consume more memory than `useMemo` and `useCallback` in order to provide a stable cache. `React` can release the cache of `useMemo` and `useCallback`, but `useMemoOne` will not release the cache until it is garbage collected.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Install
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								# npm
							 | 
						||
| 
								 | 
							
								npm install use-memo-one --save
							 | 
						||
| 
								 | 
							
								# yarn
							 | 
						||
| 
								 | 
							
								yarn add use-memo-one
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Usage
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								import { useMemoOne, useCallbackOne } from 'use-memo-one';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function App(props) {
							 | 
						||
| 
								 | 
							
								  const { name, age } = props;
							 | 
						||
| 
								 | 
							
								  const value = useMemoOne(() => ({ hello: name }), [name]);
							 | 
						||
| 
								 | 
							
								  const getAge = useCallbackOne(() => age, [age]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // ...
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Aliased imports
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You can use this `import` style drop in replacement for `useMemo` and `useCallback`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This style also plays very well with [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								import { useMemo, useCallback } from 'use-memo-one';
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								⚠️ The aliased exports `useMemo` and `useCallback` will only work if you use _only_ `use-memo-one` and will clash if you also use `useMemo` or `useCallback` from `react`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								import { useMemo, useCallback } from 'react';
							 | 
						||
| 
								 | 
							
								// ❌ naming clash
							 | 
						||
| 
								 | 
							
								import { useMemo, useCallback } from 'use-memo-one';
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## API
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								See [`useMemo`](https://reactjs.org/docs/hooks-reference.html#usememo) and [`useCallback`](https://reactjs.org/docs/hooks-reference.html#usecallback)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Linting
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`useMemo` and `useCallback` have fantastic linting rules with auto fixing in the [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks) package. In order to take advantage of these with `useMemoOne` and `useCallbackOne`, structure your import like this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								import { useMemo, useCallback } from 'use-memo-one';
							 | 
						||
| 
								 | 
							
								// Or your can alias it yourself
							 | 
						||
| 
								 | 
							
								import {
							 | 
						||
| 
								 | 
							
								  useMemoOne as useMemo,
							 | 
						||
| 
								 | 
							
								  useCallbackOne as useCallback,
							 | 
						||
| 
								 | 
							
								} from 'use-memo-one';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function App() {
							 | 
						||
| 
								 | 
							
								  const [isActive] = useState(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const onClick = useCallback(() => {
							 | 
						||
| 
								 | 
							
								    console.log('isActive', isActive);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // the input array will now be correctly checked by eslint-plugin-react-hooks
							 | 
						||
| 
								 | 
							
								  }, [isActive]);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## [`eslint`](https://eslint.org/) rules
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Here are some `eslint` rules you are welcome to use
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								  rules: {
							 | 
						||
| 
								 | 
							
								    // ...other rules
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    'no-restricted-imports': [
							 | 
						||
| 
								 | 
							
								      'error',
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        // If you want to force an application to always use useMemoOne
							 | 
						||
| 
								 | 
							
								        paths: [
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            name: 'react',
							 | 
						||
| 
								 | 
							
								            importNames: ['useMemo', 'useCallback'],
							 | 
						||
| 
								 | 
							
								            message:
							 | 
						||
| 
								 | 
							
								              '`useMemo` and `useCallback` are subject to cache busting. Please use `useMemoOne`',
							 | 
						||
| 
								 | 
							
								          },
							 | 
						||
| 
								 | 
							
								          // If you want to force use of the aliased imports from useMemoOne
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            name: 'use-memo-one',
							 | 
						||
| 
								 | 
							
								            importNames: ['useMemoOne', 'useCallbackOne'],
							 | 
						||
| 
								 | 
							
								            message:
							 | 
						||
| 
								 | 
							
								              'use-memo-one exports `useMemo` and `useCallback` which work nicer with `eslint-plugin-react-hooks`',
							 | 
						||
| 
								 | 
							
								          },
							 | 
						||
| 
								 | 
							
								        ],
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								    ],
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 |