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

[RFC] useStateRealtime #1868

Closed
liangchaofei opened this issue Sep 6, 2022 · 6 comments
Closed

[RFC] useStateRealtime #1868

liangchaofei opened this issue Sep 6, 2022 · 6 comments

Comments

@liangchaofei
Copy link
Contributor

useStateRealtime

对 useState 进行增强,第三个返回值增加了一个 get 方法,可以在设置 setState 后立即在其他地方获取到这个值。

核心特性

  • 获取 state 实时值

作用说明

  • 比如在用户 setState 操作后立即发起请求时,如果读取 state 值,是未被修改的,显然不满足我们的需要。
  • 在react的理念中render是纯的,state只与渲染有关,可以有其它的副作用需要取到最新的state,可以使用useEffect+useRef在每次视图更新后更新state最新值,如果你需要在setState->视图更新触发useEffect这段时间也能取到最新值,那么你就可以使用useStateRealtime

代码演示

::: react

import React, { useState } from 'react';
import { Button, message } from 'antd';
import useStateRealtime from '..';

export default () => {
  const [state1, setState1, getRealState1] = useStateRealtime(1);
  const clickBtn1 = () => {
    setState1(state1 + 1);
    message.info(`读取 state1 值是 ${state1},获取 getRealState1() 值是 ${getRealState1()}`);
  };

  const [state2, setState2, getRealState2] = useStateRealtime(() => 10);
  const clickBtn2 = () => {
    setState2(pre => {
      return pre + 2;
    });
    message.info(`读取 state2 值是 ${state2},获取 getRealState2() 值是 ${getRealState2()}`);
  };

  const [state3, setState3, getRealState3] = useStateRealtime(1);
  const clickBtn3 = () => {
    setState3(pre => {
      return pre + 2;
    });
    console.log(`读取 state3 值是 ${state3},获取 getRealState3() 值是 ${getRealState3()}`);
    setState3(pre => {
      return pre + 2;
    });
    console.log(`第二次读取 state3 值是 ${state3},获取 getRealState3() 值是 ${getRealState3()}`);
  };

  return (
    <div>
      <h4>初始化为值,设置状态参数为值情况</h4>
      <div>视图中的值 state1 :{state1}</div>
      <Button
        type="primary"
        onClick={() => {
          clickBtn1();
        }}
      >
        加1
      </Button>

      <hr />

      <h4>初始化参数为函数,设置状态参数为函数情况</h4>
      <div>视图中的值 state2 :{state2}</div>
      <Button
        type="primary"
        onClick={() => {
          clickBtn2();
        }}
      >
        加2
      </Button>

      <hr />
      <h4>状态参数为函数,且在批量更新的场景中也可以取到最新值</h4>
      <div>视图中的值 state3 :{state3}</div>
      <Button
        type="primary"
        onClick={() => {
          clickBtn3();
        }}
      >
        加2
      </Button>
    </div>
  );
};

:::

API

function useStateRealtime<T>(initialState: T | (() => T)): [T, Dispatch<SetStateAction<T>>, () => T]
function useStateRealtime<T = undefined>(): [T | undefined, Dispatch<SetStateAction<T | undefined>>, () => T | undefined]
const [state, setState, getRealState] = useStateRealtime(initialState);

参数

参数 说明 类型
initialState 状态初始值 T | (() => T)

返回值

参数 说明 类型
state 当前状态(同 useState 中) T | undefined
setState 设置状态值(同 useState 中) Dispatch<SetStateAction<T | undefined>>
getRealState 获取实时状态值( view 更新后真正的值) () => T | undefined

备注:类型声明

  • T 为泛型 <T>
  • type SetStateAction<S> = S | ((prevState: S) => S);
  • type Dispatch<A> = (value: A) => void;
@zq0904
Copy link

zq0904 commented Nov 14, 2023

我想知道这个 RFC 被关闭的理由
我们不可能完全依赖useEffect(() => {}, [xxx])来观测数据变动,因为它不是所见即所得的,除非你要复用多个依赖项做相同的操作

@liangchaofei
Copy link
Contributor Author

liangchaofei commented Nov 15, 2023

我想知道这个 RFC 被关闭的理由 我们不可能完全依赖useEffect(() => {}, [xxx])来观测数据变动,因为它不是所见即所得的,除非你要复用多个依赖项做相同的操作

ahooks官方实现了这个hooks,可以去官网看下。但是官网的hooks在某种情况下,拿不到最新值

@liuyib
Copy link
Collaborator

liuyib commented Nov 15, 2023

@zq0904 目前 ahooks (v3.7.8) 里没有满足这个 RFC 能力的 hook,只有一个类似的,即 useGetState,但 useGetState 没法在更新至后立即获取到最新值,还是需要在渲染下一帧才能拿到新值。所以本来计划修改 useGetState 的行为,使其能立即获取到最新值,但是这样就破坏性更新了,所以计划引入新 hook:#2348, 来实现这个功能。

可以等待 #2348 这个 PR 合入,临时的来说,你可以在自己项目中把 #2348 的实现代码复制到本地使用,等 ahooks 新版内置后,再替换成 ahooks 里的。

@zq0904
Copy link

zq0904 commented Nov 15, 2023

非常感谢你们的回答

@liangchaofei
Copy link
Contributor Author

@zq0904 目前 ahooks (v3.7.8) 里没有满足这个 RFC 能力的 hook,只有一个类似的,即 useGetState,但 useGetState 没法在更新至后立即获取到最新值,还是需要在渲染下一帧才能拿到新值。所以本来计划修改 useGetState 的行为,使其能立即获取到最新值,但是这样就破坏性更新了,所以计划引入新 hook:#2348, 来实现这个功能。

可以等待 #2348 这个 PR 合入,临时的来说,你可以在自己项目中把 #2348 的实现代码复制到本地使用,等 ahooks 新版内置后,再替换成 ahooks 里的。

我上面提的那个hooks,也能满足吧,获取到最新值。

@liuyib
Copy link
Collaborator

liuyib commented Nov 15, 2023

我上面提的那个hooks,也能满足吧,获取到最新值。

可以的,殊途同归,上述评论只是以 open 的 PR 做举例哈~

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

No branches or pull requests

3 participants