Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add useProState hook #2520

Open
wants to merge 15 commits into
base: v4
Choose a base branch
from

Conversation

coding-ice
Copy link
Contributor

@coding-ice coding-ice commented Apr 13, 2024

[中文版模板 / Chinese template]

🤔 This is a ...

  • New feature
  • Bug fix
  • Site / documentation update
  • Demo update
  • TypeScript definition update
  • Bundle size optimization
  • Performance optimization
  • Enhancement feature
  • Internationalization
  • Refactoring
  • Code style optimization
  • Test Case
  • Branch merge
  • Other (about what?)

🔗 Related issue link

close: #2432

💡 Background and solution

📝 Changelog

Language Changelog
🇺🇸 English add useProState
🇨🇳 Chinese

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • TypeScript definition is updated/provided or not needed
  • Changelog is provided or not needed

@crazylxr
Copy link
Collaborator

这个往 v4 分支合

@coding-ice coding-ice changed the base branch from master to v4 April 21, 2024 08:15
@CLAassistant
Copy link

CLAassistant commented Apr 21, 2024

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
5 out of 6 committers have signed the CLA.

✅ guoyunhe
✅ coding-ice
✅ guaijie
✅ LonelyFellas
✅ joe-leong
❌ crazylxr
You have signed the CLA already but the status is still pending? Let us recheck it.

@liuyib liuyib changed the title feat(useProState): add hook feat: add useProState hook Apr 22, 2024
config/hooks.ts Outdated Show resolved Hide resolved
@coding-ice
Copy link
Contributor Author

都可以了,分支从master切的,没太注意,抱歉~

@pangao66
Copy link

pangao66 commented Aug 25, 2024

目前的getState还是不能实时获取到期待的setState之后的值,见这个issues,#2631
我这里改写setState,在setState之前获取要赋值的新值,塞给ref,这样ref就能同步获取到最新的值了, 大佬们看看这样是否可行,有什么隐患

import { useState, type Dispatch, type SetStateAction, useCallback, useRef } from 'react';
import { isFunction } from 'ahooks/es/utils';

export type SetMergeState<S extends Record<string, never>> = <K extends keyof S>(
  state: Pick<S, K> | null | ((prevState: Readonly<S>) => Pick<S, K> | S | null),
) => void;
export type DispatchType<S> = Dispatch<SetStateAction<S>>;

function useProState<S extends Record<string, never>>(
  initialState?: S | (() => S),
): [
  S,
  {
    setState: DispatchType<S>;
    getState: () => S;
    resetState: () => void;
    setMergeState: SetMergeState<S>;
  },
];

function useProState<S>(initialState?: S | (() => S)): [
  S,
  {
    setState: DispatchType<S>;
    getState: () => S;
    resetState: () => void;
    setMergeState: (s: Record<string, never>) => void;
  },
];

function useProState<S>(initialState: S) {
  const [state, setStatePrivate] = useState<S>(initialState);
  const currentStateRef = useRef(state);

  const setState = useCallback((patch: unknown) => {
    const newState = isFunction(patch) ? patch(state) : patch;
    setStatePrivate(newState);
    currentStateRef.current = newState;
  }, [state]);
  const getState = useCallback(() => currentStateRef.current, []);

  const resetState = useCallback(() => {
    setState(initialState);
  }, []);

   const setMergeState = useCallback((patch: unknown) => {
    const newState = isFunction(patch) ? patch(state) : patch;
    const result = newState ? { ...state, ...newState } : state;
    setStatePrivate(result);
    currentStateRef.current = result;
  }, [state]);

  return [state, { setState, getState, resetState, setMergeState }];
}

export default useProState;

@crazylxr
Copy link
Collaborator

目前的getState还是不能实时获取到期待的setState之后的值,见这个issues,#2631 我这里改写setState,在setState之前获取要赋值的新值,塞给ref,这样ref就能同步获取到最新的值了, 大佬们看看这样是否可行,有什么隐患

import { useState, type Dispatch, type SetStateAction, useCallback, useRef } from 'react';
import { isFunction } from 'ahooks/es/utils';

export type SetMergeState<S extends Record<string, never>> = <K extends keyof S>(
  state: Pick<S, K> | null | ((prevState: Readonly<S>) => Pick<S, K> | S | null),
) => void;
export type DispatchType<S> = Dispatch<SetStateAction<S>>;

function useProState<S extends Record<string, never>>(
  initialState?: S | (() => S),
): [
  S,
  {
    setState: DispatchType<S>;
    getState: () => S;
    resetState: () => void;
    setMergeState: SetMergeState<S>;
  },
];

function useProState<S>(initialState?: S | (() => S)): [
  S,
  {
    setState: DispatchType<S>;
    getState: () => S;
    resetState: () => void;
    setMergeState: (s: Record<string, never>) => void;
  },
];

function useProState<S>(initialState: S) {
  const [state, setStatePrivate] = useState<S>(initialState);
  const currentStateRef = useRef(state);

  const setState = useCallback((patch: unknown) => {
    const newState = isFunction(patch) ? patch(state) : patch;
    setStatePrivate(newState);
    currentStateRef.current = newState;
  }, [state]);
  const getState = useCallback(() => currentStateRef.current, []);

  const resetState = useCallback(() => {
    setState(initialState);
  }, []);

   const setMergeState = useCallback((patch: unknown) => {
    const newState = isFunction(patch) ? patch(state) : patch;
    const result = newState ? { ...state, ...newState } : state;
    setStatePrivate(result);
    currentStateRef.current = result;
  }, [state]);

  return [state, { setState, getState, resetState, setMergeState }];
}

export default useProState;

可以考虑一下, @coding-ice 你看看呢,获取最新值的问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants