# general-store **Repository Path**: mirrors_HubSpot/general-store ## Basic Information - **Project Name**: general-store - **Description**: Simple, flexible store implementation for Flux. #hubspot-open-source - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-24 - **Last Updated**: 2026-07-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README  [](https://www.npmjs.com/package/general-store) [](https://travis-ci.org/HubSpot/general-store) `general-store` aims to provide all the features of a [Flux](http://facebook.github.io/flux/) store without prescribing the implementation of that store's data or mutations. Briefly, a store: 1. contains any arbitrary value 2. exposes that value via a get method 3. responds to specific events from the dispatcher 4. notifies subscribers when its value changes That's it. All other features, like Immutability, data fetching, undo, etc. are implementation details. Read more about the `general-store` rationale [on the HubSpot Product Team Blog](http://product.hubspot.com/blog/keeping-flux-flexible-with-general-store). ## Install ```bash # npm >= 5.0.0 npm install general-store # yarn yarn add general-store ``` ```js // namespace import import * as GeneralStore from 'general-store'; // or import just your module import { define } from 'general-store'; ``` ## Create a store GeneralStore uses functions to encapsulate private data. ```javascript var dispatcher = new Flux.Dispatcher(); function defineUserStore() { // data is stored privately inside the store module's closure var users = { 123: { id: 123, name: 'Mary', }, }; return ( GeneralStore.define() .defineName('UserStore') // the store's getter should return the public subset of its data .defineGet(function() { return users; }) // handle actions received from the dispatcher .defineResponseTo('USER_ADDED', function(user) { users[user.id] = user; }) .defineResponseTo('USER_REMOVED', function(user) { delete users[user.id]; }) // after a store is "registered" its action handlers are bound // to the dispatcher .register(dispatcher) ); } ``` If you use a singleton pattern for stores, simply use the result of `register` from a module. ```javascript import { Dispatcher } from 'flux'; import * as GeneralStore from 'general-store'; var dispatcher = new Dispatcher(); var users = {}; var UserStore = GeneralStore.define() .defineGet(function() { return users; }) .register(dispatcher); export default UserStore; ``` ## Dispatch to the Store Sending a message to your stores via the dispatcher is easy. ```javascript dispatcher.dispatch({ actionType: 'USER_ADDED', // required field data: { // optional field, passed to the store's response id: 12314, name: 'Colby Rabideau', }, }); ``` ## Store Factories The classic singleton store API is great, but can be hard to test. `defineFactory()` provides an composable alternative to `define()` that makes testing easier and allows you to extend store behavior. ```javascript var UserStoreFactory = GeneralStore.defineFactory() .defineName('UserStore') .defineGetInitialState(function() { return {}; }) .defineResponses({ USER_ADDED: function(state, user) { state[user.id] = user; return state; }, USER_REMOVED: function(state, user) { delete state[user.id]; return state; }, }); ``` Like singletons, factories have a register method. Unlike singletons, that register method can be called many times and will always return a **new instance** of the store described by the factory, which is useful in unit tests. ```javascript describe('UserStore', () => { var storeInstance; beforeEach(() => { // each test will have a clean store storeInstance = UserStoreFactory.register(dispatcher); }); it('adds users', () => { var mockUser = { id: 1, name: 'Joe' }; dispatcher.dispatch({ actionType: USER_ADDED, data: mockUser }); expect(storeInstance.get()).toEqual({ 1: mockUser }); }); it('removes users', () => { var mockUser = { id: 1, name: 'Joe' }; dispatcher.dispatch({ actionType: USER_ADDED, data: mockUser }); dispatcher.dispatch({ actionType: USER_REMOVED, data: mockUser }); expect(storeInstance.get()).toEqual({}); }); }); ``` To further assist with testing, the [`InspectStore`](https://github.com/HubSpot/general-store/blob/master/src/store/InspectStore.js) module allows you to read the internal fields of a store instance (e.g. `InspectStore.getState(store)`). ## Using the Store API A registered Store provides methods for "getting" its value and subscribing to changes to that value. ```javascript UserStore.get(); // returns {} var subscription = UserStore.addOnChange(function() { // handle changes! }); // addOnChange returns an object with a `remove` method. // When you're ready to unsubscribe from a store's changes, // simply call that method. subscription.remove(); ``` ## React GeneralStore provides some convenience functions for supplying data to React components. Both functions rely on the concept of "dependencies" and process those dependencies to return any data kept in a `Store` and make it easily accessible to a React component. ### Dependencies GeneralStore has a two formats for declaring data dependencies of React components. A `SimpleDependency` is simply a reference to a `Store` instance. The value returned will be the result of `Store.get()`. A `CompoundDependency` depends on one or more stores and uses a "dereference" function that allows you to perform operations and data manipulation on the data that comes from the `stores` listed in the dependency: ```javascript const FriendsDependency = { // compound fields can depend on one or more stores // and specify a function to "dereference" the store's value. stores: [ProfileStore, UsersStore], deref: props => { friendIds = ProfileStore.get().friendIds; users = UsersStore.get(); return friendIds.map(id => users[id]); }, }; ``` Once you declare your dependencies there are two ways to connect them to a react component. ### `useStoreDependency` `useStoreDependency` is a [React Hook](https://reactjs.org/docs/hooks-intro.html) that enables you to connect to a single dependency inside of a functional component. The `useStoreDependency` hook accepts a dependency, and optionally a map of props to pass into the `deref` and a dispatcher instance. ```javascript function FriendsList() { const friends = GeneralStore.useStoreDependency( FriendsDependency, {}, dispatcher ); return (