語法:
somecontext = createContext(defaultValue);
作用: 避免了組件嵌套太深, 頂層變量層層傳遞的麻煩.
如何消費頂層數據
第一步: 用createContext聲明一個context上下文變量
import { createContext } from 'react';export const GlobalContext = createContext({} as any);
● 參數defaultValue: 如果在組件的頂層樹沒有匹配到context Provider,就會使用defaultValue,它是靜態的并且永遠不會被改變. 如果你沒有什么特別想聲明的默認值, 寫個null就行.
● 返回值: 返回一個context對象, 它本身不帶有任何信息,它代表了其他組件可以提供和讀取的上下文.生成的context對象有兩個屬性,分別是:
○ context.Provider: 讓你用來給組件們提供context變量
○ context.Consumer: 另一種比較少用的, 用來消費context變量的方法( useContext出現之前的一種老的讀取context的方法, 不推薦使用, 現在推薦用useContext )
第二步: 用context.Provider給下層組件傳遞要消費的值
像下面這樣, 將你的子組件用context.Provider包裹, 并通過value向內部所有的組件們提供可用的值,
const globalData = Object.assign({}, {mydata,
}const [globalStore, dispatch] = useReducer(useCallback((preState, patchValue) => {return { ...preState, ...patchValue };}, []),globalData,
);function App(){return (<GlobalContext.Providervalue={{ globalStore}}<OtherComponents/></GlobalContext.Provider>)
}
第三步: 用useContext消費頂層樹提供的數據
所有子組件就可以通過調用usecontext(ThemeContext)去讀取這個context的變量,無論這些子組件嵌套有多深
const { globalStore } = useContext(GlobalContext);
function OtherComponents(){const theme = useContext(GlobalContext);return <button classname={theme}/>
}
只要來自父組件的context改變了, react就會重新渲染和更新ui
通常, 在不同文件的組件需要訪問同一個context, 這就是為什么我們要在一個單獨的文件里聲明context, 然后將它export出去
// Contexts.js
import { createContext } from 'react';export const GlobalContextProvider = GlobalContext.Provider;export default GlobalContext;
如果想在子組件更新這些數據怎么辦?
總不能從頂層傳遞一個setstate下來吧,這多麻煩啊, 特別是如果你的項目中組件嵌套很深的情況, 有個簡單的方法,就是從context.Provider的value中 pass down 一個 dispatch 函數 from useReducer via context
const globalData = Object.assign({}, {mydata,
}const [globalStore, dispatch] = useReducer(useCallback((preState, patchValue) => {return { ...preState, ...patchValue };}, []),globalData,
);function App(){return (<GlobalContext.Providervalue={{ globalStore, dispatch}} //改動在這里<OtherComponents/></GlobalContext.Provider>)
}
這樣TodosApp中所有的子組件就可以使用dispatch去更新頂層數據了
function DeepChild(props) {// If we want to perform an action, we can get dispatch from context. const dispatch = useContext(TodosDispatch);function handleClick() {dispatch({ type: 'add', text: 'hello' });}return (<button onClick={handleClick}>Add todo</button>);
}
參考自文檔: https://legacy.reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down