State and network handling in React
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?
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);
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.
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);
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.
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 useget
,set
andcall
if you wrap your component withwithTake
!