开始使用HookState库
React.js是一个成熟的JavaScript库,用于声明性和动态用户界面。React.js将用户界面分解为多个组件。在React.js编程中,状态的概念是至关重要的。
我们需要知道什么是状态,如何有效地维护它,以及如何处理随着应用程序的扩展而增加的复杂性。
在这篇文章中,我们将使用Hookstate库学习React.js中状态管理的基本知识。
前提条件
作为一个前提条件,读者必须具备以下条件。
- 一个网络浏览器,[如谷歌浏览器]。
- 一个代码编辑器,如[VS Code]或任何首选IDE。
- 对[JavaScript]编程语言的了解。
- [React库]的基础知识。
- 在你的开发环境上有一个[Node.js]LTS或更高版本。
了解状态管理
简而言之,状态管理是一种模式,我们在现代前端框架的可重复使用的组件中控制数据的通信和共享。
我们的应用程序将数据封装在一个数据结构中,该结构反映了应用程序的逻辑状态,我们可以用它来访问和改变,以便在各种状态之间转换。
应用程序的状态("state")因用户的操作而改变。
一个案例研究可以是一个电子商务应用。例如,一个电子商务网站可以有一些组件,如Button,Cart,Checkout,Login, 以及更多。
当用户向Cart 组件添加物品或执行成功登录时,这些操作将改变我们组件的状态,从而改变整个应用程序的状态。
为什么要使用状态管理库?
在现代的前端应用程序中,我们将UI分解成逻辑上可重用的组件。这些组件往往需要动态数据来共享和传递。
在一个广泛的应用程序中,保持对全局状态的跟踪,同时避免prop 钻空子可能是很困难的。这就是状态管理库的用武之地。
与redux不同的是,redux使用reducers、dispatch和action,有时会让人感到困惑,Hookstate库将React中的状态概念提升到一个新的水平。
Hookstate库将声明式ReactuseState 的理念包装成一个全局版本,并以额外的功能对其进行了扩展。
它的一些核心功能包括。
- 一个插件系统,用于持久化和状态验证来扩展库的功能。
- Hookstate的标准TypeScript对状态管理的支持。
- 支持深度嵌套组件中的异步和部分状态更新等等。
应用程序设置
为了搭建一个新的React应用程序的脚手架,我们将使用一个新的前端构建工具,Vite。
Vite通过使用Rollup而不是Webpack捆绑预配置的代码,为开发者优化了构建过程。
要用一个基本的React模板启动Vite应用程序,键入以下命令。
npm init vite@latest hookstate-demo -- --template react
接下来,在终端上导航到hookstate-demo 文件夹内,执行npm install 命令。
npm install
接下来,将hookstate 和uuid 包添加到项目中,如图所示。
npm install --save @hookstate/core uuid
最后,通过运行命令在你的浏览器上启动一个开发服务器。
npm run dev

如果我们切换到我们的浏览器并访问URLhttp://localhost:3000/ ,我们应该看到与此类似的东西。

创建全局状态
为了创建和管理全局状态,在你的src 目录中添加一个文件夹并命名为states 。
现在,我们将在states 文件夹下创建一个TaskState.js 文件,包含一个自定义的钩子。我们的函数将调用Hookstate的方法createState([]) 来创建一个新的状态并返回。
导入uuid 和@hookstate/core 包来创建一个全局状态。
import { createState, useState } from "@hookstate/core";
import {v4 as uuid} from "uuid";
注意:
useState钩子类似于React的内置钩子。当在一个文件中同时访问钩子时,一个别名有助于消除歧义。
在库的导入下面,实例化createState 来创建一个新的状态。
// Initial state - empty array.
const taskState = createState([]);
最后,让我们创建一个自定义钩子,以便在我们的组件中操作状态时重复使用。创建并导出useTaskState 函数。
export function useTaskState() {
}
在函数主体内,添加state 变量来启动来自useState 的状态。
// assign state
const state = useState(taskState);
最后,返回以下函数。
return {
// addTask method takes the new state and returns a new state using the .set(method)
addTask(newTask) {
return state.set((tasks) => [...tasks, { newTask, id: uuid() }]);
},
// filter task lists to remove a list item
removeTask(id) {
return state.set((tasks) => tasks.filter((task) => task.id !== id));
},
// state.get() retieves the Todo list state
get getTasks() {
return state.get();
}
};
让我们简单地剖析一下上面的代码片断。
addTask方法接受一个newTask参数,代表输入字段中的用户值。最后,该函数从Hookstate返回state.get,进行突变并添加新的任务。getTasks方法将通过返回 方法来访问全局存储,其工作原理与React内置的 钩子相同。state. getsetState- 最后,
removeTask方法访问全局状态并通过ID过滤出任务。
创建AddTodo组件
AddTodo 组件处理用户的输入以呈现一个新的待办事项。在components 文件夹中定义AddTodo.jsx 文件。
我们的组件将重新使用之前的自定义useTaskState ,以访问全局状态。
import { useTaskState } from "../states/TaskState";
在我们的返回语句中,我们添加一个接受新待办事项的输入表单。当用户提交表单时,我们调用onSubmit 事件处理程序来添加新的项目。
创建AddTodo 函数,如下图所示。
const AddTodo = () => {
const taskState = useTaskState();
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
// trim white spaces
if (!e.target["toDo"].value.trim()) {
return;
}
// add new to-do item
taskState.addTask(e.target["toDo"].value);
e.target["toDo"].value = "";
}}
>
{/*An input element and a button */}
<input name="toDo" />
<button type="submit">Add Todo</button>
</form>
</div>
);
};
最后,默认导出我们的函数。
export default AddTodo;
TodoList组件
TodoList 组件包含我们的todo 项目。在你的components 文件夹内,添加带有以下代码的TodoList.jsx 文件。
import { useTaskState } from "../states/TaskState";
const ToDoList = () => {
const taskState = useTaskState();
const state = taskState.getTasks;
return (
<ul>
{state.length > 0 &&
state.map((todo) => (
<li key={todo.id}>
<span>{todo.text}</span>
{/*Add a delete button*/}
<button onClick={() => taskState.removeTask(todo.id)}>
Delete
</button>
</li>
))}
</ul>
);
};
export default ToDoList;
在上面的代码中,我们做了以下工作。
- 首先,我们从我们的
states文件夹中导入useState自定义挂钩。 const state = taskState.getTasks;是访问我们状态的变量。- 在JSX里面,我们通过循环返回一个带有可用任务列表的
<ul>元素。
App.js组件
我们的主App.js 文件是相当小的。我们需要添加的是ToDoList 组件、AddTodo 组件和useTaskState 。
import { useTaskState } from "./states/TaskState";
import ToDoList from "./components/ToDoList";
import AddTodo from "./components/AddTodo";
最后,导出App 组件,并将这些组件映射到JSX中。
export default function App() {
const taskState = useTaskState();
return (
<div className="App">
<h1>TODO APP</h1>
<AddTodo />
<ToDoList />
</div>
);
}
演示
要运行这个程序,在你的终端上用命令启动一个开发服务器。
npm run dev
如果我们回到我们的浏览器http://localhost:3000/ ,我们最终的应用程序应该与此相似。

结论
本教程向你介绍了React中使用Hookstate的状态管理。为了生成全局状态和访问状态存储,我们建立了一个使用该库的API的Todo应用。