From c3e09ed7456dc2fb15fb1aff31bf352eb3e2a569 Mon Sep 17 00:00:00 2001 From: Michael Peyper Date: Mon, 7 Dec 2020 20:54:32 +1100 Subject: [PATCH] Capture all results a rendered hook produces. (#496) feat: Capture all results a rendered hook produces as `result.all` Fixes #461 Co-authored-by: Josh Ellis --- docs/api-reference.md | 8 ++++++-- src/pure.js | 17 ++++++++++------- test/resultHistory.test.js | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 test/resultHistory.test.js diff --git a/docs/api-reference.md b/docs/api-reference.md index 117e755f..a3cc05e5 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -63,13 +63,17 @@ The `renderHook` function returns an object that has the following properties: ```js { + all: Array current: any, error: Error } ``` -The `current` value or the `result` will reflect whatever is returned from the `callback` passed to -`renderHook`. Any thrown values will be reflected in the `error` value of the `result`. +The `current` value or the `result` will reflect the latest of whatever is returned from the +`callback` passed to `renderHook`. Any thrown values from the latest call will be reflected in the +`error` value of the `result`. The `all` value is an array containing all the returns (including the +most recent) from the callback. These could be `result` or an `error` depending on what the callback +returned at the time. ### `rerender` diff --git a/src/pure.js b/src/pure.js index 53ef84c5..435d0736 100644 --- a/src/pure.js +++ b/src/pure.js @@ -21,25 +21,28 @@ function Fallback() { } function resultContainer() { - let value = null - let error = null + const results = [] const resolvers = [] const result = { + get all() { + return results.map(({ value, error }) => error || value) + }, get current() { + const { value, error } = results[results.length - 1] if (error) { throw error } return value }, get error() { + const { error } = results[results.length - 1] return error } } - const updateResult = (val, err) => { - value = val - error = err + const updateResult = (value, error) => { + results.push({ value, error }) resolvers.splice(0, resolvers.length).forEach((resolve) => resolve()) } @@ -48,8 +51,8 @@ function resultContainer() { addResolver: (resolver) => { resolvers.push(resolver) }, - setValue: (val) => updateResult(val), - setError: (err) => updateResult(undefined, err) + setValue: (value) => updateResult(value), + setError: (error) => updateResult(undefined, error) } } diff --git a/test/resultHistory.test.js b/test/resultHistory.test.js new file mode 100644 index 00000000..80b9b10b --- /dev/null +++ b/test/resultHistory.test.js @@ -0,0 +1,34 @@ +import { renderHook } from '../src' + +describe('result history tests', () => { + let count = 0 + function useCounter() { + const result = count++ + if (result === 2) { + throw Error('expected') + } + return result + } + + test('should capture all renders states of hook', () => { + const { result, rerender } = renderHook(() => useCounter()) + + expect(result.current).toEqual(0) + expect(result.all).toEqual([0]) + + rerender() + + expect(result.current).toBe(1) + expect(result.all).toEqual([0, 1]) + + rerender() + + expect(result.error).toEqual(Error('expected')) + expect(result.all).toEqual([0, 1, Error('expected')]) + + rerender() + + expect(result.current).toBe(3) + expect(result.all).toEqual([0, 1, Error('expected'), 3]) + }) +})