Fre.js Hooks 完全指南:深入理解 useState、useEffect 等核心API
Fre.js 是一个轻量级的 Concurrent UI 库,其 Hooks 系统为开发者提供了简洁而强大的状态管理和副作用处理能力。本文将带你全面掌握 Fre.js 中 useState、useEffect 等核心 Hooks 的使用方法,帮助你轻松构建高效的现代前端应用。
一、Fre.js Hooks 简介
Fre.js 的 Hooks 系统借鉴了 React Hooks 的设计理念,但针对自身轻量级特性进行了优化。通过 Hooks,你可以在函数组件中使用状态和其他 React 特性,而无需编写类组件。Fre.js 的 Hooks 实现位于 src/hook.ts 文件中,包含了一系列用于状态管理、副作用处理、性能优化等的钩子函数。
二、核心 Hooks 详解
2.1 useState:状态管理的基石
useState 是 Fre.js 中最基础也最常用的 Hook,它允许你在函数组件中添加状态。其基本用法如下:
const [state, setState] = useState(initialState);
从 src/hook.ts 的源码可以看出,useState 实际上是基于 useReducer 实现的:
export const useState = <T>(initState: T | (() => T)) => {
return useReducer<T, SetStateAction<T>>(null, initState)
}
这意味着 useState 本质上是 useReducer 的一种简化形式,适用于简单的状态管理场景。在实际应用中,你可以像这样使用 useState:
import { useState } from '../../src/index'
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
2.2 useEffect:处理副作用
useEffect 允许你在函数组件中执行副作用操作,如数据获取、订阅或手动修改 DOM。其基本用法如下:
useEffect(() => {
// 副作用操作
return () => {
// 清理函数
};
}, [dependencies]);
从 src/hook.ts 中可以看到,useEffect 的实现调用了 effectImpl 函数:
export const useEffect = (cb: EffectCallback, deps?: DependencyList) => {
return effectImpl(cb, deps!, 'effect')
}
effectImpl 函数会根据依赖数组的变化来决定是否执行副作用。当依赖数组发生变化时,useEffect 会先执行上一次的清理函数(如果有的话),然后再执行新的副作用函数。
下面是一个使用 useEffect 的实际例子,来自 demo/src/use-effect.tsx:
import { render, useState, useEffect, h } from '../../src'
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
return () => {
// 清理函数,在组件卸载或依赖变化时执行
console.log('Cleanup function');
};
}, [count]); // 仅在 count 变化时执行
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
2.3 其他常用 Hooks
除了 useState 和 useEffect,Fre.js 还提供了其他常用的 Hooks:
- useReducer:用于处理复杂状态逻辑,比 useState 更适合管理包含多个子值的状态对象。
- useMemo:用于记忆计算结果,避免不必要的重复计算,提高性能。
- useCallback:用于记忆函数,避免不必要的函数重新创建。
- useRef:用于创建一个持久化的引用,可用于访问 DOM 元素或存储不需要触发重渲染的数据。
- useContext:用于在组件树中共享状态,避免 props drilling。
这些 Hooks 的实现都可以在 src/hook.ts 文件中找到。
三、Hooks 使用规则
使用 Fre.js Hooks 时,需要遵循以下规则:
- 只能在函数组件或自定义 Hook 的顶层调用 Hooks,不要在循环、条件或嵌套函数中调用。
- 只能在 Fre.js 函数组件或自定义 Hook 中调用 Hooks。
这些规则确保 Fre.js 能够正确地跟踪 Hooks 的调用顺序,从而正确地管理组件状态。
四、实际应用示例
下面是一个结合使用多个 Hooks 的示例,来自 demo/src/with-jotal.tsx:
import { useState, useEffect, render, h } from "../../src/index";
function TodoApp() {
const [todos, setTodos] = useState([]);
const [inputValue, setInputValue] = useState("");
useEffect(() => {
// 从本地存储加载 todos
const savedTodos = localStorage.getItem("todos");
if (savedTodos) {
setTodos(JSON.parse(savedTodos));
}
}, []);
useEffect(() => {
// 将 todos 保存到本地存储
localStorage.setItem("todos", JSON.stringify(todos));
}, [todos]);
const handleAddTodo = () => {
if (inputValue.trim()) {
setTodos([...todos, { text: inputValue, completed: false }]);
setInputValue("");
}
};
const handleToggleTodo = (index) => {
const newTodos = [...todos];
newTodos[index].completed = !newTodos[index].completed;
setTodos(newTodos);
};
return (
<div>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleAddTodo}>Add Todo</button>
<ul>
{todos.map((todo, index) => (
<li
key={index}
style={{ textDecoration: todo.completed ? "line-through" : "none" }}
onClick={() => handleToggleTodo(index)}
>
{todo.text}
</li>
))}
</ul>
</div>
);
}
render(<TodoApp />, document.getElementById("app"));
在这个示例中,我们使用了 useState 来管理 todos 和 inputValue 状态,使用了两个 useEffect 分别用于从本地存储加载数据和将数据保存到本地存储。
五、总结
Fre.js Hooks 为开发者提供了一种简洁、灵活的方式来管理组件状态和副作用。通过 useState、useEffect 等核心 Hooks,你可以编写出更加简洁、可维护的代码。无论是构建简单的 UI 组件还是复杂的应用,Fre.js Hooks 都能帮助你提高开发效率,改善代码质量。
如果你想深入了解 Fre.js Hooks 的实现细节,可以查看 src/hook.ts 文件。同时,demo/src 目录下的示例代码也是学习如何使用这些 Hooks 的好资源。
希望本文能够帮助你更好地理解和使用 Fre.js Hooks。开始使用 Fre.js Hooks,构建你的下一个精彩应用吧!
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0153- DDeepSeek-V4-ProDeepSeek-V4-Pro(总参数 1.6 万亿,激活 49B)面向复杂推理和高级编程任务,在代码竞赛、数学推理、Agent 工作流等场景表现优异,性能接近国际前沿闭源模型。Python00
LongCat-Video-Avatar-1.5最新开源LongCat-Video-Avatar 1.5 版本,这是一款经过升级的开源框架,专注于音频驱动人物视频生成的极致实证优化与生产级就绪能力。该版本在 LongCat-Video 基础模型之上构建,可生成高度稳定的商用级虚拟人视频,支持音频-文本转视频(AT2V)、音频-文本-图像转视频(ATI2V)以及视频续播等原生任务,并能无缝兼容单流与多流音频输入。00
auto-devAutoDev 是一个 AI 驱动的辅助编程插件。AutoDev 支持一键生成测试、代码、提交信息等,还能够与您的需求管理系统(例如Jira、Trello、Github Issue 等)直接对接。 在IDE 中,您只需简单点击,AutoDev 会根据您的需求自动为您生成代码。Kotlin03
Intern-S2-PreviewIntern-S2-Preview,这是一款高效的350亿参数科学多模态基础模型。除了常规的参数与数据规模扩展外,Intern-S2-Preview探索了任务扩展:通过提升科学任务的难度、多样性与覆盖范围,进一步释放模型能力。Python00
skillhubopenJiuwen 生态的 Skill 托管与分发开源方案,支持自建与可选 ClawHub 兼容。Python0112