首页 > 解决方案 > 在不使用任何第三方状态管理库的情况下,在反应中创建自定义钩子状态并从任何地方操纵全局状态

问题描述

您可以在此StackBlitz 链接中获取,参考这里

todoState.tsmodels项目文件夹中有一个文件夹文件。这todoState.ts用于使用自定义挂钩管理应用程序的全局状态。我需要在全局上执行以下任务todoState.ts..

  1. 添加新状态
  2. 移除状态
  3. 更新状态

这是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 />. 这里...

  1. <TodoForm />, 用于添加要列出的任务。
  2. <TodoListLineItem />, 用于显示从 TodoForm 组件添加的所有任务。当用户将鼠标悬停在每个待办事项列表项上时,用户可以从全局管理状态中删除特定的任务项。

一种是实现此全局管理状态功能的最佳且可重用的方法?

一个组件如何将状态从 A 更改为 B 仅通过操作应用程序的全局状态对象就反映在相关组件上。如果我投入useState([])index.tsx它会运作良好,但我想从TodoState.ts文件中管理状态。谢谢你。

导出默认 todoState;

标签: javascriptreactjstypescriptreact-hooks

解决方案


最后,我发现并学习了 React-Context API 的新概念。你可以在这里查看StackBlitz Link

为了管理全局状态,React 提供了 context-api。仅当您在组件树中从上到下传递多级组件属性时才使用。我使用非常小的示例来了解我不同用例的上下文 API。

首先,我们需要使用两个上下文..

  1. createContext [用于创建全局状态上下文]
  2. 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 链接中附加的完整工作演示。


推荐阅读