react-ion-store

Logo

State and network handling in React

View the Project on GitHub jeroenptrs/react-ion-store

Getting values

The not so great way: Consumer

As discussed in the setup guide, you can use the Consumer component to get data from the store by wrapping the Consumer around your return values. Say you want to get the title of you app from the store and display it in a component called MyTitle:

import React from "react";
import { Consumer } from "react-ion-store";

const MyTitle = () => (
  <Consumer>{store => <h1>{store.get("title")}</h1>}</Consumer>
);

export default MyTitle;

This is not ideal, what if we want to perform actions with this title, either in our render function or some place else?

The preferred way: withStore

That’s where the withStore Higher-Order Component comes into play:

import React from "react";
import { withStore } from "react-ion-store";

class MyTitle extends React.Components {
  render() {
    const { store } = this.props;
    return <h1>{store.get("title")}</h1>;
  }
}

export default withStore(MyTitle);

This way we can access the store straight from our component’s props, getting access to all the store API’s in the process.

We wrote the above example as a class, but you can write your component as an arrow function in the same way:

const MyTitle = ({ store }) => <h1>{store.get("title")}</h1>;

export default withStore(MyTitle);

Getting more than one value

Up until now, we’ve asked the store to retrieve just one value. This is done by passing the key as a string value in the store.get command.

But, we can ask the store to get us multiple or even all values. In either of these situations, the store will return an object, a flattened representation of the store in it’s current iteration, instead of a singular value.

Multiple values

Let’s expand on our previous examples, say we want to make not just a title component, but a header component. We added a subtitle to our store, which we’re now retrieving as well.

You could do this with two store.get commands, but there’s simpler way by passing both keys in an array to the command:

import React from "react";
import { withStore } from "react-ion-store";

class MyHeader extends React.Component {
  render() {
    const { title, subtitle } = this.props.store.get(["title", "subtitle"]);
    return (
      <div className="header">
        <h1>{title}</h1>
        <p>{subtitle}</p>
      </div>
    );
  }
}

export default withStore(MyHeader);

All values

This one is even simpler, you just call the store.get function:

import React from "react";
import { withStore } from "react-ion-store";

class MyHeader extends React.Component {
  render() {
    const { title, subtitle } = this.props.store.get();
    return (
      <div className="header">
        <h1>{title}</h1>
        <p>{subtitle}</p>
      </div>
    );
  }
}

export default withStore(MyHeader);

What’s not so optimal about this approach is that you’re requesting the entire store when you don’t need it. If you’re making components that are about just displaying data, even having functions like set and call (which we will discuss later on) takes up unnecessary real estate.

Flattening your data: withTake

Using withTake, you’re passing the values you define straight to the props, skipping the store. This is great, as mentioned above, if you’re in a component that just needs to show data and nothing else, as with our header component:

import React from "react";
import { withStore, withTake } from "react-ion-store";
import { compose } from "recompose";

const takeKeys = ["title", "subtitle"]);

class MyHeader extends React.Component {
  render() {
    const { title, subtitle } = this.props;
    return (
      <div className="header">
        <h1>{title}</h1>
        <p>{subtitle}</p>
      </div>
    );
  }
}

export default compose(
  withStore,
  withTake(takeKeys)
)(MyHeader);

or using an arrow function:

const takeKeys = ["title", "subtitle"]);

const MyHeader = ({ title, subtitle }) => (
  <div className="header">
    <h1>{title}</h1>
    <p>{subtitle}</p>
  </div>
);

export default compose(
  withStore,
  withTake(takeKeys)
)(MyHeader);

Taking one, multiple or all values works the same way as with store.get.

NOTE!

withTake flattens your store down to the keys you provide and removes all API’s! You will not be able to use get, set and call if you wrap your component with withTake!