本文演示瞭如何使用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 } });