javascript - 在不使用任何第三方状态管理库的情况下,在反应中创建自定义钩子状态并从任何地方操纵全局状态
问题描述
您可以在此StackBlitz 链接中获取,参考这里
我todoState.ts
在models
项目文件夹中有一个文件夹文件。这todoState.ts
用于使用自定义挂钩管理应用程序的全局状态。我需要在全局上执行以下任务todoState.ts
..
- 添加新状态
- 移除状态
- 更新状态
这是todoState.ts
.
import { useState, useEffect } from "react";
const todoState = (todo?, callback?) => {
const [todos, setTodos] = useState([todo]);
useEffect(()=>{
setTodos(todo);
},[])
return [{todos, setTodos}];
}
现在,我有两个依赖于 globalState 的用户定义组件。是 1.<TodoForm />
和<TodoListLineItem />
以上两个组件都呈现在index.tsx
.
如何管理所有组件的全局状态,包括index.tsx
, <TodoForm />
, <TodoListLineItem />
. 这里...
<TodoForm />
, 用于添加要列出的任务。<TodoListLineItem />
, 用于显示从 TodoForm 组件添加的所有任务。当用户将鼠标悬停在每个待办事项列表项上时,用户可以从全局管理状态中删除特定的任务项。
哪一种是实现此全局管理状态功能的最佳且可重用的方法?
一个组件如何将状态从 A 更改为 B 仅通过操作应用程序的全局状态对象就反映在相关组件上。如果我投入useState([])
,index.tsx
它会运作良好,但我想从TodoState.ts
文件中管理状态。谢谢你。
导出默认 todoState;
解决方案
最后,我发现并学习了 React-Context API 的新概念。你可以在这里查看StackBlitz Link
为了管理全局状态,React 提供了 context-api。仅当您在组件树中从上到下传递多级组件属性时才使用。我使用非常小的示例来了解我不同用例的上下文 API。
首先,我们需要使用两个上下文..
- createContext [用于创建全局状态上下文]
- useContext [用于从子组件的上下文中获取状态]。
为了使用 Context,我创建了一个<context.Provider>
组件。并且所有状态管理任务仅使用此组件级别完成。所有子组件只发送要做什么的事件。并且提供者组件的全局上下文相应地改变。
首先,创建上下文..
export interface ItodoContext{
todoState? : Itodo[];
addNewTodoState?: (state?: string) => void;
removeTodoItemByIndex? : (index?: number) => void;
}
export const todoContext = createContext<ItodoContext[]>([{}]);
因为,我正在使用 React-Typescript 功能组件,根据上下文接口我定义了所有状态任务。我传递了所有的 TodoState,操作 TodoState 的函数,如 addNewTodoState、removeTodoItemByIndex。
然后创建上下文提供者..
const allTodoStates = {
todoState,
addNewTodoState,
removeTodoItemByIndex
}
return(
<todoContext.Provider value = { [allTodoStates]}>
{props.children}
</todoContext.Provider>
)
然后我将 Provider 设置为 index.tsx 组件中树中的父组件,如下所示..
const App: FC = () => {
return (
<div className="h-100 w-100">
<TodoStateProvider>
<Navbar />
<div className="container">
<TodoForm />
<TodoListLineItem />
</div>
</TodoStateProvider>
</div>
);
}
参见上面的所有组件现在是<TodoStateProvider>
父组件的子组件。
当我需要在上下文中添加新状态时,<TodoForm>
我们如何添加状态如下代码......
const [{addNewTodoState}] = useContext(todoContext);
const sendTodoItem = (e) => {
addNewTodoState(todoInput.trim());
}
等等..提供者组件具有value
属性,我们可以使用 useContext() 钩子从子组件中获取这些属性。正如我们上面使用的。请参阅我在上面的 StackBlitz 链接中附加的完整工作演示。
推荐阅读
- c# - 如何忽略运算符重载
- c# - 通过示例了解六角端口和适配器的概念
- rabbitmq - 面临安装 RabbitMQ 管理控制台插件的问题
- sql - oracle查询的查询优化
- android - 无法解决:将 google-services 更新到 15.0.0 后 play-services-basement
- google-maps - 谷歌地图不使用文本节点呈现 SVG 元素
- google-analytics - Google Analytics(分析)1 天活跃用户报告不一致
- r - 由于非英文字母导致 casefold() 出现问题
- python - python列表格式化和替换数据
- javascript - 如果链接存在图像,则返回 true 否则为 false