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,构建你的下一个精彩应用吧!
GLM-5智谱 AI 正式发布 GLM-5,旨在应对复杂系统工程和长时域智能体任务。Jinja00
GLM-5-w4a8GLM-5-w4a8基于混合专家架构,专为复杂系统工程与长周期智能体任务设计。支持单/多节点部署,适配Atlas 800T A3,采用w4a8量化技术,结合vLLM推理优化,高效平衡性能与精度,助力智能应用开发Jinja00
jiuwenclawJiuwenClaw 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。Python0203- QQwen3.5-397B-A17BQwen3.5 实现了重大飞跃,整合了多模态学习、架构效率、强化学习规模以及全球可访问性等方面的突破性进展,旨在为开发者和企业赋予前所未有的能力与效率。Jinja00
AtomGit城市坐标计划AtomGit 城市坐标计划开启!让开源有坐标,让城市有星火。致力于与城市合伙人共同构建并长期运营一个健康、活跃的本地开发者生态。01
awesome-zig一个关于 Zig 优秀库及资源的协作列表。Makefile00