反应 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 视为组件的依赖注入。