diff --git a/docs/guide/upgrade.en-US.md b/docs/guide/upgrade.en-US.md index 991704f02b..1cb2f30922 100644 --- a/docs/guide/upgrade.en-US.md +++ b/docs/guide/upgrade.en-US.md @@ -36,7 +36,7 @@ useRequest has been rewritten: - Removed `pagination` related options, it is recommended to use `usePagination` or `useAntdTable` to achieve paging ability. - Removed `loadMore` related options, it is recommended to use `useInfiniteScroll` to achieve unlimited loading ability. - Removed `fetchKey`, that is, deleted concurrent request. -- Removed `formatResult`, `initialData`, and `thrownError`. +- Removed `formatResult`, `initialData`, and `throwOnError`. - The request library is no longer integrated by default, and `service` no longer supports string or object. - Added `runAsync` and `refreshAsync`, the original `run` no longer returns Promise. - Added error retry ability. diff --git a/docs/guide/upgrade.zh-CN.md b/docs/guide/upgrade.zh-CN.md index ab37a65a0f..56234df363 100644 --- a/docs/guide/upgrade.zh-CN.md +++ b/docs/guide/upgrade.zh-CN.md @@ -36,7 +36,7 @@ useRequest 完全进行了重写: - 删除了 `pagination` 相关属性,建议使用 `usePagination` 或 `useAntdTable` 来实现分页能力。 - 删除了 `loadMore` 相关属性,建议使用 `useInfiniteScroll` 来实现无限加载能力。 - 删除了 `fetchKey`,也就是删除了并行能力。 -- 删除了 `formatResult`、`initialData`、`thrownError`。 +- 删除了 `formatResult`、`initialData`、`throwOnError`。 - 不再默认集成请求库,`service` 不再支持字符或对象。 - 新增了 `runAsync` 和 `refreshAsync`,原来的 `run` 不再返回 Promise。 - 新增了错误重试能力。 diff --git a/packages/hooks/src/useResetState/__tests__/index.test.ts b/packages/hooks/src/useResetState/__tests__/index.test.ts index 8728302445..b4fa76640b 100644 --- a/packages/hooks/src/useResetState/__tests__/index.test.ts +++ b/packages/hooks/src/useResetState/__tests__/index.test.ts @@ -2,9 +2,9 @@ import { act, renderHook } from '@testing-library/react'; import useResetState from '../index'; describe('useResetState', () => { - const setUp = (initialState: S) => + const setUp = (initialState) => renderHook(() => { - const [state, setState, resetState] = useResetState(initialState); + const [state, setState, resetState] = useResetState(initialState); return { state, @@ -20,6 +20,13 @@ describe('useResetState', () => { expect(hook.result.current.state).toEqual({ hello: 'world' }); }); + it('should support functional initialValue', () => { + const hook = setUp(() => ({ + hello: 'world', + })); + expect(hook.result.current.state).toEqual({ hello: 'world' }); + }); + it('should reset state', () => { const hook = setUp({ hello: '', @@ -49,4 +56,38 @@ describe('useResetState', () => { }); expect(hook.result.current.state).toEqual({ count: 1 }); }); + + it('should keep random initial state', () => { + const random = Math.random(); + const hook = setUp({ + count: random, + }); + + act(() => { + hook.result.current.setState({ count: Math.random() }); + }); + + act(() => { + hook.result.current.resetState(); + }); + + expect(hook.result.current.state).toEqual({ count: random }); + }); + + it('should support random functional initialValue', () => { + const random = Math.random(); + const hook = setUp(() => ({ + count: random, + })); + + act(() => { + hook.result.current.setState({ count: Math.random() }); + }); + + act(() => { + hook.result.current.resetState(); + }); + + expect(hook.result.current.state).toEqual({ count: random }); + }); }); diff --git a/packages/hooks/src/useResetState/demo/demo1.tsx b/packages/hooks/src/useResetState/demo/demo1.tsx index 5a98c7f876..d77bd29ecf 100644 --- a/packages/hooks/src/useResetState/demo/demo1.tsx +++ b/packages/hooks/src/useResetState/demo/demo1.tsx @@ -1,33 +1,37 @@ -import React from 'react'; +import React, { useMemo } from 'react'; +import { Button, Space } from 'antd'; import { useResetState } from 'ahooks'; -interface State { - hello: string; - count: number; -} - export default () => { - const [state, setState, resetState] = useResetState({ + const initialValue = { hello: '', - count: 0, - }); + value: Math.random(), + }; + const initialValueMemo = useMemo(() => { + return initialValue; + }, []); + + const [state, setState, resetState] = useResetState(initialValue); return (
+
initial state:
+
{JSON.stringify(initialValueMemo, null, 2)}
+
current state:
{JSON.stringify(state, null, 2)}
-

- - - -

+ set hello and value + + +
); }; diff --git a/packages/hooks/src/useResetState/index.ts b/packages/hooks/src/useResetState/index.ts index bcff86c842..eaa7d6000e 100644 --- a/packages/hooks/src/useResetState/index.ts +++ b/packages/hooks/src/useResetState/index.ts @@ -1,16 +1,25 @@ -import { useState } from 'react'; +import { useRef, useState } from 'react'; import type { Dispatch, SetStateAction } from 'react'; +import { isFunction } from '../utils'; import useMemoizedFn from '../useMemoizedFn'; +import useCreation from '../useCreation'; type ResetState = () => void; const useResetState = ( initialState: S | (() => S), ): [S, Dispatch>, ResetState] => { - const [state, setState] = useState(initialState); + const initialStateRef = useRef(initialState); + const initialStateMemo = useCreation( + () => + isFunction(initialStateRef.current) ? initialStateRef.current() : initialStateRef.current, + [], + ); + + const [state, setState] = useState(initialStateMemo); const resetState = useMemoizedFn(() => { - setState(initialState); + setState(initialStateMemo); }); return [state, setState, resetState];