Context + Hook + HOC 實現React的狀態管理

在使用React開發一個應用時,咱們有時會遇到組件樹中位置不一樣,層級不一樣的n多個組件須要狀態共享的問題,咱們能夠使用redux/mobx來管理,固然context也爲咱們提供一個可行方案。react

先上一個實現效果:redux

點擊changeUser按鈕後:image.pngapp

能夠考慮分幾個步驟來實現:ide

第一,準備好要共享狀態的組件:

// app.jsx
import React from 'react';
import HomePage from "./page/HomePage";
// 引入context的provider組件
import { AppProvider } from "./store/appContext";

function App() {
  return (
    <div className="App">
      App
      <AppProvider>
        <HomePage name={1} />
      </AppProvider>
    </div>
  );
}

export default App;複製代碼

第二,建立context,提供provider將須要共享狀態的組件外層包裹,提供consumer高階組件將須要消費狀態的組件進行加工;

// appContext.js
import React, { createContext, useReducer } from 'react';
const AppContext = createContext();

function AppProvider(props) {
    const initialState = {
        user: "Amy Tong"
    };
    const reducer = (state, action) => {
        const { type, payload } = action;
        switch (type) {
            case "SET_USER":
                return { ...state, user: payload }
            default:
                break;
        }
    }
    const [state, dispatch] = useReducer(reducer, initialState)
    return (
        <AppContext.Provider value={{ state, dispatch }}>
            {props.children}
        </AppContext.Provider>
    )
}

const AppConsumer = Cmp => {
    return props => {
        return <AppContext.Consumer>
            {(ctx) => <Cmp {...props} {...ctx} />}
        </AppContext.Consumer>
    }
}
// 或以下的方法也能夠
const AppConsumer = Cmp => {
  return props => {
    const ctx = useContext(AppContext);
    return <Cmp {...props} {...ctx} />;
  };
};

export { AppProvider, AppConsumer, AppContext };複製代碼

第四,在HomePage組件中使用consumer,且經過props獲取和修改狀態值;

// HomePage.js
import React from 'react';
// 引入appContext 提供的consumer高階組件
import { AppConsumer } from "../store/appContext";

function HomePage(props) {
    const { state, dispatch } = props;
    const changeUser = () => {
        dispatch({ type: "SET_USER", payload: "Mike" })
    }
    return (
        <div>
            homepage
            {JSON.stringify(state)}
            <button onClick={changeUser}>changeUser</button>
        </div>
    )
};

export default AppConsumer(HomePage);複製代碼
相關文章
相關標籤/搜索