存取儲存庫
React Redux 提供的 API 可讓您的元件傳送動作並訂閱儲存庫的資料更新。
因此,React Redux 省去了您使用何種儲存庫以及該儲存庫互動的詳細處理的細節。在一般使用情況下,您自己的元件永遠不需要在意這些細節,也不會直接參考儲存庫。React Redux 內部也會處理將儲存庫和狀態傳遞給連接元件的詳細資訊,因此這預設會依預期運作。
不過,在某些使用案例中,您可能需要自訂儲存庫和狀態傳遞給連接元件的方式,或直接存取儲存庫。以下列出一些執行此操作的方式範例。
了解如何使用 Context
在內部,React Redux 使用 React 的「context」功能,讓 Redux 儲存庫可供深入巢狀的連接元件使用。從 React Redux 6 版開始,這通常由 React.createContext()
產生的單一預設 context 物件執行,稱為 ReactReduxContext
。
React Redux 的 <Provider>
元件使用 <ReactReduxContext.Provider>
,將 Redux 儲存庫和目前儲存庫狀態置入 context,而 connect
使用 useContext(ReactReduxContext)
來讀取這些值和處理更新。
使用 useStore
鉤子
useStore
鉤子返回來自預設 ReactReduxContext
的當前儲存體執行個體。如果你真的需要存取儲存體,建議採用這種方法。
提供自訂內容
你可能提供你自己的自訂內容執行個體,而不是使用來自 React Redux 的預設內容執行個體。
<Provider context={MyContext} store={store}>
<App />
</Provider>
如果你提供自訂內容,React Redux 會使用該內容執行個體,而不是預設建立並輸出的內容執行個體。
提供自訂內容到 <Provider />
後,你會需要提供此內容執行個體到你所有的已連接元件,預期這些元件會連線到相同的儲存體
// You can pass the context as an option to connect
export default connect(
mapState,
mapDispatch,
null,
{ context: MyContext }
)(MyComponent)
// or, call connect as normal to start
const ConnectedComponent = connect(
mapState,
mapDispatch
)(MyComponent)
// Later, pass the custom context as a prop to the connected component
<ConnectedComponent context={MyContext} />
當 React Redux 在它正在尋找的內容中找不到儲存體時,會發生下列執行時期錯誤。例如
- 你提供自訂內容執行個體到
<Provider />
,但沒有提供相同的執行個體(或沒有提供任何執行個體)到你的已連接元件。 - 你提供自訂內容到你的已連接元件,但沒有提供相同的執行個體(或沒有提供任何執行個體)到
<Provider />
。
不變式違反
找不到 "儲存體" 於 "Connect(MyComponent)" 的內容中。請用
<Provider>
包住根元件,或傳遞自訂 React 內容提供者到<Provider>
,並將對應的 React 內容消費者傳遞到連接選項的 Connect(Todo)。
自訂內容與鉤子 API
透過鉤子 API 存取自訂內容,你可以使用 鉤子產生函式 建立自訂鉤子。
多個儲存體
Redux 是設計用來使用單一儲存體的。不過,如果你遇到無法避免非得使用多個儲存體的情況,那麼從 v6 起你可以透過提供(多個)自訂內容,來達成這件事。這也能自然地隔離儲存體,因為它們存在於不同的內容執行個體內。
// a naive example
const ContextA = React.createContext(null);
const ContextB = React.createContext(null);
// assuming reducerA and reducerB are proper reducer functions
const storeA = createStore(reducerA);
const storeB = createStore(reducerB);
// supply the context instances to Provider
function App() {
return (
<Provider store={storeA} context={ContextA} />
<Provider store={storeB} context={ContextB}>
<RootModule />
</Provider>
</Provider>
);
}
// fetch the corresponding store with connected components
// you need to use the correct context
connect(mapStateA, null, null, { context: ContextA })(MyComponentA)
// You may also pass the alternate context instance directly to the connected component instead
<ConnectedMyComponentA context={ContextA} />
// it is possible to chain connect()
// in this case MyComponent will receive merged props from both stores
compose(
connect(mapStateA, null, null, { context: ContextA }),
connect(mapStateB, null, null, { context: ContextB })
)(MyComponent);
直接使用 ReactReduxContext
在少數情況下,你可能需要在你自己的元件中直接存取 Redux 儲存體。你可以透過自行呈現適當的內容消費者,並存取該內容值中的 store
欄位,來達成這件事。
這並不被視為 React Redux 公開 API 的一部分,並可能在沒有通知的情況下中斷。我們確實認識到社群有必要使用案例,並將嘗試讓使用者能夠在 React Redux 之上建立其他功能,但我們對內容的特定使用被視為實作細節。如果您有其他使用案例未被目前的 API 充分涵蓋,請提交問題以討論可能的 API 改進。
import { ReactReduxContext } from 'react-redux'
// Somewhere inside of a <Provider>
function MyConnectedComponent() {
// Access the store via the `useContext` hook
const { store } = useContext(ReactReduxContext)
// alternately, use the render props form of the context
/*
return (
<ReactReduxContext.Consumer>
{({ store }) => {
// do something useful with the store, like passing it to a child
// component where it can be used in lifecycle methods
}}
</ReactReduxContext.Consumer>
)
*/
}