在使用React开发一个应用时,我们有时会遇到组件树中位置不同,层级不同的n多个组件需要状态共享的问题,我们可以使用redux/mobx来管理,当然context也为我们提供一个可行方案。
先上一个实现效果:
点击changeUser按钮后:
可以考虑分几个步骤来实现:
第一,准备好要共享状态的组件:
// 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);
关于react的context API 使用,见文档:https://react.docschina.org/docs/context.html