Coder Social home page Coder Social logo

jonbnewman / mobx-store-provider Goto Github PK

View Code? Open in Web Editor NEW
40.0 3.0 3.0 1.2 MB

React Hooks to connect mobx-state-tree to your components

Home Page: https://mobx-store-provider.jonbnewman.dev

License: MIT License

TypeScript 100.00%
react hooks mobx-state-tree mobx observable state-management mst functional state react-hooks typescript

mobx-store-provider's Introduction

mobx-store-provider

CircleCI Coverage Status

NPM Package Typescript Package size MIT License

mobx-store-provider is a library that provides React Hooks to setup and access mobx-state-tree models from within React Function Components.

Its goal is to provide a straight-forward, minimalist, and terse API that allows you to easily incorporate mobx-state-tree into functional React components.

  1. Installation
  2. Basic example
  3. API details and examples
  4. Multiple stores
  5. Local state
  6. Typescript
  7. Testing
  8. Motivation
  9. Upgrading 1.x -> 2.x

Installation

npm i mobx-store-provider
yarn add mobx-store-provider

Basic example

The following shows an example application using mobx-store-provider.

App component

At the core of the application we define the main App component.

Inside of the App we use hooks provided by mobx-store-provider to:

  1. Create the appStore instance with the useCreateStore hook
  2. Retrieve the Provider with the useProvider hook
// App.jsx (Main App component, we use it to create and provide the store)
import React from "react";
import { useProvider, useCreateStore } from "mobx-store-provider";
import AppStore from "./AppStore";
import UserDisplay from "./UserDisplay";

function App() {
  // Create the AppStore instance
  const appStore = useCreateStore(AppStore, { user: "Jonathan" });

  // Get the Provider for the AppStore
  const Provider = useProvider(AppStore);

  // Wrap the application with the Provider passing it the appStore
  return (
    <Provider value={appStore}>
      <UserDisplay />
    </Provider>
  );
}

export default App;

Note that we wrap the application with the Provider, supplying it the appStore as its value.

This makes the appStore available to the rest of the application.

Using the store

In another component somewhere in the application we want to use or gain access to the appStore.

To do this, we use the useStore hook:

// UserDisplay.jsx (A component, we use the store from above inside it)
import React from "react";
import { observer } from "mobx-react";
import { useStore } from "mobx-store-provider";
import AppStore from "./AppStore";

function UserDisplay() {
  // Get access to the store
  const appStore = useStore(AppStore);
  return <div>{appStore.user}</div>;
}

// Wrap it with mobx-react observer(), so updates get rendered
export default observer(UserDisplay);

Note that we also wrap the component with observer() from the mobx-react library.

This is critical, as it ensures the component will render any updates made to the appStore. For more information, see the observer documentation for the mobx-react library.

Defining the store

The code above uses the AppStore mobx-state-tree model. In the context of mobx-store-provider this is referred to as a store.

// AppStore.js (mobx-state-tree store/model)
import { types } from "mobx-state-tree";

const AppStore = types.model({
  user: types.string,
});

export default AppStore;

If you are new to mobx-state-tree, it is recommended you read through the mobx-state-tree documentation.


See the full docs

mobx-store-provider's People

Contributors

dependabot[bot] avatar jonbnewman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mobx-store-provider's Issues

Be more explicit in multiple stores docs

When I was new to MST I glossed over of the same type (not understanding what it meant) in this:

You may have a need to instantiate multiple stores/models (of the same type) for your particular application. **mobx-store-provider** supports this use case via a unique `identifier` you can pass into the [useProvider](/api/useProvider) and [useStore](/api/useStore) hooks.

Accordingly when I added a new store (definition, not instance) I created a new nested <Provider> (as show on that page). In hindsight I think the RootStore pattern would have been more appropriate, but I wasn't aware of it because that page is titled Multiple stores.

Would you accept a PR to put a ⚠️ on that Multiple stores page that using a single provider and the RootStore approach is better* if you only have one instance of each model type?

* I argue that it's better for this reason.

Suggestion: rename createStore to useCreateStore

When first looking at code using this library, it's hard to guess that createStore is a hook.

I believe following the pattern of prefixing it with use would better describe it.

This change would require a breaking update, but it can be preceded by a deprecation period, updating the docs to favor the new method.

Suggestion: mapStateToProps name is misleading

The mapStateToProps parameter in useStore(identifier, mapStateToProps) is used to map a store to a "view" of it, there are no props on that. I understand the name was taken from redux inject, where it does make sense, but I don't think that's the case in this library

I believe it would be more suitable to call it mapStore or something along that.

Store gets recreated everytime component is re-rendered

When using useCreateStore, the factory method gets called whenever the host component is re-rendered.

I believe this is not the expected behavior, but some code might be relying on this.

This happens because it's called on the hook body:

function useCreateStore(factory: Factory): any {
  return useRef(factory()).current;
}

My suggestion is to replace this call with a memo-d value:

function useCreateStore(factory: Factory, deps: any = []) : any {
  return useMemo(factory, deps);
}

Issues with es6 modules in Jest

Thanks for this nice library and the effort spent creating it.

Just to let you know I had issues with ES6 and Jest, it seems your library is not transformed into ES5 when publishing, is that the case or I missing something? So when trying to run a test in Jest (using default create-react-app configuration), I get the following error:

 PASS  src/atoms/Clock/Clock.test.tsx
 FAIL  src/organisms/Header/Header.test.tsx
  ● Test suite failed to run

    /Users/alanrubin/Keytree/Sense/matrix-sense-signage-ui/node_modules/mobx-store-provider/lib/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import useProvider from "./hooks/useProvider";
                                                                                                    ^^^^^^^^^^^

    SyntaxError: Unexpected identifier

      3 | import Clock from 'atoms/Clock'
      4 | import { observer } from 'mobx-react'
    > 5 | import { useStore } from 'mobx-store-provider'
        | ^
      6 | import { IAppStore } from 'models/AppStore'
      7 | import MatrixLogo from './matrix-logo.svg'

That seems to be caused because jest doesn't transpile the node_modules dir - I solved by adding to the package.json a jest configuration to transpile your library in node_modules:

"jest": {
    "transformIgnorePatterns": [
      "node_modules/(?!mobx-store-provider)/"
    ]
  }

But isn't it better to have the library published transpiled?

Thanks,
Alan

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.