本文演示了如何使用React hooks和context 实现简单简单的data store和状态管理. 假设你对如下内容有基本了解(若是没有请google):html
当提到状态管理咱们首先都会想到Redux,在react项目中这几乎已经成为事实标准。Redux的优势无需多说,然而不少时候像Redux的做者说的同样,你可能不须要Redux。 在某些场景中可能context api就能够知足你的需求。在实际使用中,你可能发现不少地方和Redux的设计不谋而合,实际上Redux底层也使用了Context Api.react
闲话少说,开始上代码!redux
├── TodoContext.jsx // context ├── TodoProvider.js // context provider ├── components // react components ├── index.jsx ├── stores │ ├── reducer.js // data store reducer │ └── util.js └── useTodo.js // customer hooks
为了实现状态管理,咱们建立一个context来保存todo数据的状态:api
export const TodoContext = React.createContext(undefined);
这样咱们就能够在咱们的React组件中使用它,这里假设咱们有一个todoState
对象,下面会讲到如何生成它:mvc
const App = {children} => ( <TodoContext.Provider value={todoState}> {children} </TodoContext.Provider> );
如今咱们建立了Context,在组件中也引入了,那么如何在子组件中使用context,以及如何传入初始状态,和修改状态呢? 咱们来看一下如何结合React Hooks的方法来使用context。dom
首先咱们来封装一个Provider对象,这个provider对象接受一个useReducer的执行结果,也就是上文提到的todoState对象。能够理解为一个[data, dispatcher]
.这里的state和dispatcher的概念和Redux中很是类似。ide
export const TodoProvider = ({ reducer, initialState, children }) => ( <TodoContext.Provider value={useReducer(reducer, initialState)}> {children} </TodoContext.Provider> );
看到这里愈来愈熟悉,这不就是redux中的reducer嘛 ? 没错,reducer的做用就是根据不一样的action和payload的组合,更新state中的数据。google
export const reducer = (state, action) => { const { id, text } = action.payload || { id: undefined, text: undefined }; const { todos, visibilityFilter } = state; switch (action.type) { case "ADD_TODO": return { todos: [ { id: Math.random() .toString(16) .substring(2), completed: false, text }, ...todos ], visibilityFilter }; case "DELETE_TODO": return { todos: todos.filter(todo => todo.id !== id), visibilityFilter }; // ....... 略
有了TodoProvider,如今App.tsx中引用方式变成以下,同时咱们在这里传入了initState。spa
const initialState = { todos: [ { text: "React Hooks", completed: false, id: 0 }, { text: "Context", completed: true, id: 1 } ], visibilityFilter: "All" }; const App = () => ( <TodoProvider initialState={initialState} reducer={reducer}> <div> <Header /> <MainSection /> </div> </TodoProvider> );
有了state和reducer方法,怎么在组件中使用他们呢? 换句redux的话说如何把state和actionDispatcher和组件connect起来? 答案是useContext!这里咱们建立了一个custom hooks,任何使用咱们想使用todoState的时候,能够直接使用useTodo。设计
export const useTodo = () => useContext(TodoContext);
在组件中的用法:
// 引入 const [{ todos, visibilityFilter }, dispatch] = useTodo(); // 建立新TODO dispatch({ type: "ADD_TODO", payload: { text } });