讓開發者可以更容易的從母元件傳遞 state 到深層的子元件,並讓多個用到的 state 資料的元件可以隨著資料變動而更新。
const value = useContext(MyContext);
接收一個 context 物件,回傳該 context 內的值。
首先在 authContext.js 這隻檔案中建立 Context,順便可以把相關的 Provider 寫好。
// authContext.js
import React, { useState } from "react";
const AuthContext = React.createContext({
isLoggedIn: false,
onLogout: () => {},
onLogin: (email, password) => {}
});
export const AuthContextProvider = (props) => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const logoutHandler = () => {
setIsLoggedIn(false);
};
const loginHandler = () => {
setIsLoggedIn(true);
};
return (
<AuthContext.Provider
// 記得提供 context 給 Provider
value={{
isLoggedIn: isLoggedIn,
onLogout: logoutHandler,
onLogin: loginHandler
}}
>
{props.children}
</AuthContext.Provider>
);
};
export default AuthContext;
然後可以把 Provider 包住你想傳遞的子元件,這裡範例包住 App 元件,實際上還是看需求,不一定要包到那麼父層的元件
// index.js
import ReactDOM from "react-dom";
import App from "./App";
import { AuthContextProvider } from "./authContext";
const rootElement = document.getElementById("root");
ReactDOM.render(
<AuthContextProvider>
<App />
</AuthContextProvider>,
rootElement
);
在 App.js 中透過 useContext 取得 context
// App.js
import React, { useContext } from "react";
import AuthContext from "./authContext";
const App = () => {
const ctx = useContext(AuthContext);
return (
<>
{!ctx.isLoggedIn && (
<button onClick={() => ctx.onLogin("Tom", "123")}>Login</button>
)}
{ctx.isLoggedIn && <button onClick={() => ctx.onLogout()}>Logout</button>}
</>
);
};
export default App;
因為有用到 context 的元件在 context 更新時都會 re-render,所以比較不常變動的值才建議使用 context。
React.memo、useMemo 會在之後做介紹
根據這篇文章的結尾一段文章:
Context API 的本意並不是讓我們進行多層 state 的管理,而是讓多個共用資料的元件能夠方便隨著資料的更動而被更新。因此 React 才會讓使用 useContext 的元件都重新渲染