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`', | ||
|  |           }, | ||
|  |         ], | ||
|  |       }, | ||
|  |     ], | ||
|  |   }, | ||
|  | }; | ||
|  | ``` |