前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >React 中使用 Vue3.6 Vapor 同款 Signal 是一种什么体验?

React 中使用 Vue3.6 Vapor 同款 Signal 是一种什么体验?

作者头像
萌萌哒草头将军
发布2025-03-06 23:44:38
发布2025-03-06 23:44:38
400
代码可运行
举报
文章被收录于专栏:前端框架前端框架
运行总次数:0
代码可运行

React Signals 是一个轻量级的状态管理库,它提供了一种简单而强大的方式来管理 React 应用中的状态。它的 API 设计受到了 SolidJS 的启发,使用起来非常直观。

该架构和被合入vue3.6 vapor分支的alien-signals 是一样的!

地址:https://github.com/hunghg255/reactjs-signal/tree

基础用法

1. 创建信号 (createSignal)

代码语言:javascript
代码运行次数:0
复制
import { createSignal } from "reactjs-signal";

// 创建一个初始值为 0 的信号
export const count = createSignal(0);

2. 在组件中使用信号

有三种主要方式可以在组件中使用信号:

2.1 使用 useSignal(获取值和设置器)
代码语言:javascript
代码运行次数:0
复制
import { useSignal } from "reactjs-signal";
import { count } from "../signals/counter";

export const Counter = () => {
  const [value, setValue] = useSignal(count);

  return (
    <div>
      <p>Count: {value}</p>
      <button onClick={() => setValue((v) => v + 1)}>Increment</button>
    </div>
  );
};
2.2 使用 useSignalValue(仅获取值)
代码语言:javascript
代码运行次数:0
复制
import { useSignalValue } from "reactjs-signal";
import { count } from "../signals/counter";

export const Display = () => {
  const value = useSignalValue(count);

  return <div>Current count: {value}</div>;
};
2.3 使用 useSetSignal(仅获取设置器)
代码语言:javascript
代码运行次数:0
复制
import { useSetSignal } from "reactjs-signal";
import { count } from "../signals/counter";

export const Controls = () => {
  const setCount = useSetSignal(count);

  return (
    <div>
      <button onClick={() => setCount((v) => v + 1)}>+1</button>
      <button onClick={() => setCount((v) => v - 1)}>-1</button>
    </div>
  );
};

3. 计算信号 (createComputed)

计算信号允许你基于其他信号创建派生状态:

代码语言:javascript
代码运行次数:0
复制
import { createSignal, createComputed } from "reactjs-signal";

const count = createSignal(0);
const doubleCount = createComputed(() => count() * 2);
const isEven = createComputed(() => count() % 2 === 0);

4. 信号效果 (useSignalEffect)

使用 useSignalEffect 可以在信号值变化时执行副作用:

代码语言:javascript
代码运行次数:0
复制
import { useSignalEffect } from "reactjs-signal";
import { count } from "../signals/counter";

export const Logger = () => {
  useSignalEffect(() => {
    console.log("Count changed:", count());
  });

  return null;
};

5. 服务端渲染支持 (useHydrateSignal)

如果你需要在服务端渲染时初始化信号值:

代码语言:javascript
代码运行次数:0
复制
import { useHydrateSignal } from "reactjs-signal";
import { count } from "../signals/counter";

export const App = () => {
  // 在组件挂载时将 count 信号的值设置为 10
  useHydrateSignal(count, 10);

  return <div>...</div>;
};

一点点心得

  • 使用 useSignalValue 当只需要读取值时
  • 使用 useSetSignal 当只需要更新值时
  • 适当使用 createComputed 来缓存计算结果

实践:todo 应用

代码语言:javascript
代码运行次数:0
复制
import { createSignal, createComputed } from"reactjs-signal";

exportinterface Todo {
  id: number;
  text: string;
  completed: boolean;
}

exportconst todos = createSignal<Todo[]>([]);
exportconst filter = createSignal<"all" | "active" | "completed">("all");

exportconst filteredTodos = createComputed(() => {
const currentFilter = filter();
const currentTodos = todos();

switch (currentFilter) {
    case"active":
      return currentTodos.filter((todo) => !todo.completed);
    case"completed":
      return currentTodos.filter((todo) => todo.completed);
    default:
      return currentTodos;
  }
});
代码语言:javascript
代码运行次数:0
复制
import { useSignal, useSignalValue } from"reactjs-signal";
import { todos, filter, filteredTodos } from"../signals/todos";

exportconst TodoApp = () => {
const [, setTodos] = useSignal(todos);
const [currentFilter, setFilter] = useSignal(filter);
const visibleTodos = useSignalValue(filteredTodos);

const addTodo = (text: string) => {
    setTodos((prev) => [
      ...prev,
      {
        id: Date.now(),
        text,
        completed: false,
      },
    ]);
  };

return (
    <div>
      <input
        type="text"
        onKeyPress={(e) => {
          if (e.key === "Enter") {
            addTodo(e.currentTarget.value);
            e.currentTarget.value = "";
          }
        }}
      />
      <ul>
        {visibleTodos.map((todo) => (
          <li key={todo.id}>{todo.text}</li>
        ))}
      </ul>
      <div>
        <button onClick={() => setFilter("all")}>All</button>
        <button onClick={() => setFilter("active")}>Active</button>
        <button onClick={() => setFilter("completed")}>Completed</button>
      </div>
    </div>
  );
};

记住,信号的主要优势在于其简单性和响应式特性,这使得状态管理变得更加直观和高效。

最后

今天的分享就到这里了,如果文章中有问题,欢迎指正!

如果对你有帮助,记得关注我

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 萌萌哒草头将军 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基础用法
    • 1. 创建信号 (createSignal)
    • 2. 在组件中使用信号
      • 2.1 使用 useSignal(获取值和设置器)
      • 2.2 使用 useSignalValue(仅获取值)
      • 2.3 使用 useSetSignal(仅获取设置器)
    • 3. 计算信号 (createComputed)
    • 4. 信号效果 (useSignalEffect)
    • 5. 服务端渲染支持 (useHydrateSignal)
    • 一点点心得
  • 实践:todo 应用
    • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档