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: 增加usePublisherState Hook #2329

Closed
wants to merge 1 commit into from

Conversation

Song-aff
Copy link

[English Template / 英文模板]

🤔 这个变动的性质是?

  • 新特性提交
  • 日常 bug 修复
  • 站点、文档改进
  • 演示代码改进
  • TypeScript 定义更新
  • 包体积优化
  • 性能优化
  • 功能增强
  • 国际化改进
  • 重构
  • 代码风格优化
  • 测试用例
  • 分支合并
  • 其他改动(是关于什么的改动?)

🔗 相关 Issue

💡 需求背景和解决方案

基于配置的页面级的组件在前端开发当中越来越普遍(如procomponents),在受控模式下,需要对局部进行更新也需要对重新生成整个配置,导致页面的额外渲染。通过开发基于订阅发布的状态管理办法,在需要更新的局部组件中主动进行订阅,避免页面不必要的重绘。

usePublisherState

基于发布订阅的 state 方法的 Hooks,与useSubscriberState结合使用。更新 state 时只会触发主动通过useSubscriberState接收的组件重渲染。

代码演示

基础用法

import { usePublisherState, useSubscriberState } from 'ahooks';
import type { PublisherStateType } from 'ahooks';
import React, { useState } from 'react';
const InnerComp: React.FC<{ data: PublisherStateType<number>; data1: number }> = ({
  data,
  data1,
}) => {
  const counter = useSubscriberState(data);
  return (
    <div>
      <p>
        Child counter: {counter},{data1}
      </p>
    </div>
  );
};
export default () => {
  const [counter, setCounter] = usePublisherState(0);
  const [counter1, setCounter1] = useState(0);
  return (
    <div>
      <p>
        <button
          type="button"
          onClick={() => setCounter((val) => val + 1)}
          style={{ margin: '0 16px' }}
        >
          counter++ with usePublisherState
        </button>
        <button type="button" onClick={() => setCounter1((val) => val + 1)}>
          counter++ with useState
        </button>
      </p>

      <p>
        Parent counter: {counter.current},{counter1}
      </p>
      <InnerComp data={counter} data1={counter1} />
    </div>
  );
};

API

usePublisherState

type PublisherStateType<T> = {
  current: T;
  observable: Observable<string>;
};
type SetPublisherStateType<T> = (newVal: T | ((newVal: T) => T), needUpdate?: boolean) => void;

const [state, setState] = usePublisherState<T>(
  initialState: T,
): [PublisherStateType, SetPublisherStateType]

基于发布订阅的 state 方法的 Hooks。用于定义和管理状态。返回一个元组,包含当前状态对象和更新状态的方法。

  • initialState: T: 初始状态的值。

useSubscriberState

const state = useSubscriberState<T>(
  state: PublisherStateType<T>,
): T

基于发布订阅的 state 方法的 Hooks。用于订阅状态的更新。返回当前状态的值。

  • state: PublisherStateType<T>: usePublisherState返回的状态对象。

📝 更新日志

语言 更新描述
🇺🇸 英文
🇨🇳 中文

☑️ 请求合并前的自查清单

⚠️ 请自检并全部勾选全部选项⚠️

  • 文档已补充或无须补充
  • 代码演示已提供或无须提供
  • TypeScript 定义已补充或无须补充
  • Changelog 已提供或无须提供

@CLAassistant
Copy link

CLAassistant commented Sep 23, 2023

CLA assistant check
All committers have signed the CLA.

@liuyib
Copy link
Collaborator

liuyib commented Sep 26, 2023

这个功能,社区里很成熟的状态库,是不是都已经涵盖了?没必要重复造轮子。

见这个讨论:#1832

ahooks 团队不太倾向于重复造轮子

@liuyib
Copy link
Collaborator

liuyib commented Sep 26, 2023

社区的成熟状态库,例如 Mobx,原理也是发布订阅,和 Mobx 相比,这个 hook 轻量是轻量了,但是一旦复杂场景满足不了,还是要上专业的状态库

此外,目前来看,这个新 hook 的发布订阅,只支持单消息仓库,全局只能用一次。例如,用来存商品信息后,再存聊天消息,它们之间的消息发布就冲突了(发布聊天信息时,商品的订阅者也会收到消息),需要用 Map 重构。另外还需要消息去重(需要用 Set 处理)、计算值等功能,这些 Mobx 已经支持的必须的基础能力,没有加上。

以上,目前的实现还没法投入实际使用。

@liuyib
Copy link
Collaborator

liuyib commented Sep 27, 2023

见:#2076 (comment)

ahooks 不倾向造状态管理的轮子,这个就先关闭了~ 感谢贡献

@liuyib liuyib closed this Sep 27, 2023
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.

None yet

3 participants