反应 Mobx 上下文提供者
React Mobx ContextProvider
您能否向我解释一下为什么在将 mobx 与 React Context 结合使用时我需要将我的应用程序包装在 Store Provider 中。我的意思是:
// Create Counter Store
class CounterStore {
constructor() {
makeAutoObservable(this)
this.num = 0
}
inc() { this.num++ }
}
// Create React Context with store
const StoreContext = React.createContext(new CounterStore())
// Create hook for usage context
const useStore = () => React.useContext(StoreContext)
// Create component
const Counter = observer(() => {
const counterStore = useStore()
return (
<>
<div>{counterStore.num}</div>
<button onClick={() => counterStore.inc()}>
inc num
</button>
</>
)
})
// Create App component
const App = () => {
return (
<Counter />
)
}
好的,一切正常,我可以访问我的计数器组件内的商店。
但我仍然没有将我的应用打包到商店提供商中,例如:
/// same code as above with little change
// Now create context with no value:
const StoreContext = React.createContext()
// And create Provider with store.
const StoreProvider = ({children}) => {
return <StoreContext.Provider value={new CounterStore()}>
{children}
</StoreContext.Provider>
}
Then wrap App component with provider:
render(
<StoreProvider>
<App />
</StoreProvider>,
document.getElementById("root")
);
此代码也有效。但是我不明白为什么我需要创建 SroreProvider 并用它包装我的应用程序,如果没有它一切正常
简短回答:如果您的上下文有默认存储值,则不一定需要用 Provider
包装所有内容。一切都会正常工作,因为 MobX 为观察者组件创建了自己的订阅机制,允许它们重新渲染。 (也值得一读 this docs 以了解如果你不使用 MobX 为什么你可能想要上下文)
更重要的是,在那种情况下你甚至可能根本不需要上下文。您可以只创建商店的单例实例并直接将其导入到您需要的地方,而不必理会提供者。
但有时您可能希望了解提供商的情况。例如用于服务器端渲染,或用于测试目的。想象一下,您的 inc
方法进行了一些 api 调用。但是对于测试你不想这样做,并且在测试时你可以用不同的商店替换你的商店:
const TestStoreProvider = ({children}) => {
// With provider you can different store there
return <StoreContext.Provider value={new CounterStoreForTests()}>
{children}
</StoreContext.Provider>
}
在这种情况下,您可以将 Provider
视为组件的依赖注入。
您能否向我解释一下为什么在将 mobx 与 React Context 结合使用时我需要将我的应用程序包装在 Store Provider 中。我的意思是:
// Create Counter Store
class CounterStore {
constructor() {
makeAutoObservable(this)
this.num = 0
}
inc() { this.num++ }
}
// Create React Context with store
const StoreContext = React.createContext(new CounterStore())
// Create hook for usage context
const useStore = () => React.useContext(StoreContext)
// Create component
const Counter = observer(() => {
const counterStore = useStore()
return (
<>
<div>{counterStore.num}</div>
<button onClick={() => counterStore.inc()}>
inc num
</button>
</>
)
})
// Create App component
const App = () => {
return (
<Counter />
)
}
好的,一切正常,我可以访问我的计数器组件内的商店。
但我仍然没有将我的应用打包到商店提供商中,例如:
/// same code as above with little change
// Now create context with no value:
const StoreContext = React.createContext()
// And create Provider with store.
const StoreProvider = ({children}) => {
return <StoreContext.Provider value={new CounterStore()}>
{children}
</StoreContext.Provider>
}
Then wrap App component with provider:
render(
<StoreProvider>
<App />
</StoreProvider>,
document.getElementById("root")
);
此代码也有效。但是我不明白为什么我需要创建 SroreProvider 并用它包装我的应用程序,如果没有它一切正常
简短回答:如果您的上下文有默认存储值,则不一定需要用 Provider
包装所有内容。一切都会正常工作,因为 MobX 为观察者组件创建了自己的订阅机制,允许它们重新渲染。 (也值得一读 this docs 以了解如果你不使用 MobX 为什么你可能想要上下文)
更重要的是,在那种情况下你甚至可能根本不需要上下文。您可以只创建商店的单例实例并直接将其导入到您需要的地方,而不必理会提供者。
但有时您可能希望了解提供商的情况。例如用于服务器端渲染,或用于测试目的。想象一下,您的 inc
方法进行了一些 api 调用。但是对于测试你不想这样做,并且在测试时你可以用不同的商店替换你的商店:
const TestStoreProvider = ({children}) => {
// With provider you can different store there
return <StoreContext.Provider value={new CounterStoreForTests()}>
{children}
</StoreContext.Provider>
}
在这种情况下,您可以将 Provider
视为组件的依赖注入。