use-context-store
Easily create Redux stores inside of a React context, and access them with a useReducer-style hook
Install
npm i use-context-store
Usage
Create the Context Store
Use the createContextStore()
function to create a Redux store inside of a React context. It returns an object containing a <StoreProvider />
, a useStore()
hook, and a connectStore()
HOC.
// shopping-cart-store.js const defaultState = items: const shoppingCartStore = useShoppingCart: shoppingCartStoreuseStore ShoppingCartProvider: shoppingCartStoreStoreProvider
Provide the Store Context to your Components
Use the <StoreProvider />
we just created to... provide the store to any children components.
// app.jsx import React from 'react'import ShoppingCartProvider from '../store/shopping-cart/shopping-cart-store'import MainContent from './main-content'import CartSidebar from './cart-sidebar' const MyApp = <ShoppingCartProvider> <div ="main"> <MainContent /> <CartSidebar /> </div> </ShoppingCartProvider>
Use the Store in your Child Components
useStore
Way
The You can use the useStore()
hook we created (we renamed it useShoppingCart
).
// MainContent.jsx import React from 'react'import useShoppingCart from '../store/shopping-cart/shopping-cart-store' const MainContent = const state dispatch = return <div> stateitemslength > 10 && <span>Enough shopping just buy the stuff already</span> /* ...some other main content stuff... */ </div>
// CartSidebar.jsx import React from 'react'import useShoppingCart from '../store/shopping-cart/shopping-cart-store'import beginCheckout clearCart from '../store/shopping-cart/action-creators' const CartSidebar = items beginCheckout clearCart <div> <ul> items </ul> <span></span> <button =>Clear Cart</button> <button =>Checkout</button> </div> const ConnectedCartSidebar = const state dispatch = return <CartSidebar = =
connectStore
Way
The I'm still going back and forth on whether or not I want a connectStore
HOC (see Redux connect). On the one hand, it works really great if you are only connecting one store, and you have a bunch of actions (it just maps the dispatch for you to all of the actions, so in your inner component you can just call them directly from props and it takes away the (...args) => dispatch(actionCreator(...args))
boilerplate). It also makes testing less questionable, since you end up with a pure component with no hooks or logic in it. Connecting multiple stores to one component doesn't work great with a connect
HOC - in those cases, the useStore
hook is better for sure.
Composing multiple Provier wrappers
This looks bad 👎
const MyApp = <UserProvider> <ShoppingCartProvider> <OtherProvider> <KewlKontextProvider> <div ="main"> <MainContent /> <CartSidebar /> </div> </KewlKontextProvider> </OtherProvider> </ShoppingCartProvider> </UserProvider>
This looks better 👍
const providers = UserProvider ShoppingCartProvider OtherProvider KewlKontextProvider; const MainStoreProvider = const MyApp = <MainStoreProvider> <div ="main"> <MainContent /> <CartSidebar /> </div> </MainStoreProvider>