use-memo-one
Advanced tools
Comparing version 0.0.1 to 0.0.2
{ | ||
"name": "use-memo-one", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "useMemo and useCallback, but without cache invalidation", | ||
"main": "src/index.js", | ||
"main": "dist/memoize-one.cjs.js", | ||
"module": "dist/memoize-one.esm.js", | ||
"sideEffects": false, | ||
"author": "Alex Reardon <alexreardon@gmail.com>", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/alexreardon/use-memo-one.git" | ||
}, | ||
"peerDependencies": { | ||
@@ -10,0 +15,0 @@ "react": "^16.8.6" |
@@ -5,2 +5,8 @@ # useMemoOne | ||
[![Build Status](https://travis-ci.org/alexreardon/use-memo-one.svg?branch=master)](https://travis-ci.org/alexreardon/use-memo-one) | ||
[![npm](https://img.shields.io/npm/v/use-memo-one.svg)](https://www.npmjs.com/package/use-memo-one) | ||
[![dependencies](https://david-dm.org/alexreardon/use-memo-one.svg)](https://david-dm.org/alexreardon/use-memo-one) | ||
[![min](https://img.shields.io/bundlephobia/min/use-memo-one.svg)](https://www.npmjs.com/package/use-memo-one) | ||
[![minzip](https://img.shields.io/bundlephobia/minzip/use-memo-one.svg)](https://www.npmjs.com/package/use-memo-one) | ||
## Background | ||
@@ -12,3 +18,3 @@ | ||
`useMemoOne` and `useCallbackOne` are `concurrent mode` friendly 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 so long as there is no input change. | ||
`useMemoOne` and `useCallbackOne` are `concurrent mode` friendly 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 so long as there is no input change. | ||
@@ -33,3 +39,5 @@ ## Install | ||
const getAge = useCallbackOne(() => age, [age]) | ||
// ... | ||
} | ||
``` |
// @flow | ||
import React, { type Node } from 'react'; | ||
import { mount } from 'enzyme'; | ||
import { useMemoOne } from '../src'; | ||
import { useCallbackOne } from '../src'; | ||
type WithMemoProps = {| | ||
type Props = {| | ||
inputs: mixed[], | ||
children: (value: mixed) => Node, | ||
getResult: () => mixed, | ||
callback: Function, | ||
|}; | ||
function WithMemo(props: WithMemoProps) { | ||
const value: mixed = useMemoOne(props.getResult, props.inputs); | ||
return props.children(value); | ||
function WithCallback(props: Props) { | ||
const fn: Function = useCallbackOne(props.callback, props.inputs); | ||
return props.children(fn); | ||
} | ||
it('should not break the cache on multiple calls', () => { | ||
it('should return the passed callback until there is an input change', () => { | ||
const mock = jest.fn().mockReturnValue(<div>hey</div>); | ||
const callback = () => {}; | ||
const wrapper = mount( | ||
<WithMemo inputs={[1, 2]} getResult={() => ({ hello: 'world' })}> | ||
<WithCallback inputs={[1, 2]} callback={callback}> | ||
{mock} | ||
</WithMemo>, | ||
</WithCallback>, | ||
); | ||
@@ -27,61 +28,27 @@ | ||
expect(mock).toHaveBeenCalledTimes(1); | ||
expect(mock).toHaveBeenCalledWith({ hello: 'world' }); | ||
const initial: mixed = mock.mock.calls[0][0]; | ||
expect(initial).toEqual({ hello: 'world' }); | ||
mock.mockClear(); | ||
expect(mock).toHaveBeenCalledWith(callback); | ||
const first: mixed = mock.mock.calls[0][0]; | ||
expect(first).toBe(callback); | ||
wrapper.setProps({ inputs: [1, 2] }); | ||
expect(mock).toHaveBeenCalledWith(initial); | ||
const second: mixed = mock.mock.calls[0][0]; | ||
// same reference | ||
expect(initial).toBe(second); | ||
}); | ||
it('should break the cache when the inputs change', () => { | ||
const mock = jest.fn().mockReturnValue(<div>hey</div>); | ||
const wrapper = mount( | ||
<WithMemo inputs={[1, 2]} getResult={() => ({ hello: 'world' })}> | ||
{mock} | ||
</WithMemo>, | ||
); | ||
expect(mock).toHaveBeenCalledTimes(1); | ||
expect(mock).toHaveBeenCalledWith({ hello: 'world' }); | ||
const initial: mixed = mock.mock.calls[0][0]; | ||
expect(initial).toEqual({ hello: 'world' }); | ||
mock.mockClear(); | ||
// no input change | ||
// changing the reference to the callback function (will happen on each render) | ||
wrapper.setProps({ inputs: [1, 2], callback: () => ({ hello: 'world' }) }); | ||
// inputs are different | ||
wrapper.setProps({ inputs: [1, 2, 3] }); | ||
expect(mock).toHaveBeenCalledWith(initial); | ||
expect(mock).toHaveBeenCalledTimes(1); | ||
const second: mixed = mock.mock.calls[0][0]; | ||
// different reference | ||
expect(initial).not.toBe(second); | ||
}); | ||
// same reference | ||
expect(second).toBe(first); | ||
it('should use the latest get result function when the cache breaks', () => { | ||
const mock = jest.fn().mockReturnValue(<div>hey</div>); | ||
const wrapper = mount( | ||
<WithMemo inputs={[1, 2]} getResult={() => ({ hello: 'world' })}> | ||
{mock} | ||
</WithMemo>, | ||
); | ||
expect(mock).toHaveBeenCalledTimes(1); | ||
expect(mock).toHaveBeenCalledWith({ hello: 'world' }); | ||
const initial: mixed = mock.mock.calls[0][0]; | ||
expect(initial).toEqual({ hello: 'world' }); | ||
mock.mockClear(); | ||
// inputs are different | ||
wrapper.setProps({ | ||
inputs: [1, 2, 3], | ||
getResult: () => ({ different: 'value' }), | ||
}); | ||
// input change | ||
// changing the reference to the callback function (will happen on each render) | ||
const newCallback = () => {}; | ||
wrapper.setProps({ inputs: [1, 2, 3], callback: newCallback }); | ||
expect(mock).toHaveBeenCalledWith({ different: 'value' }); | ||
expect(mock).toHaveBeenCalledTimes(1); | ||
const third: mixed = mock.mock.calls[0][0]; | ||
// same reference | ||
expect(third).toBe(newCallback); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
453720
46
6063
40
0
3