When building web applications, we often need to interact with Browser APIs such as LocalStorage. When working with Redux Observable, we should always consider the Epic as the first place to access these as it keeps the logic away from our components. In this lesson we’ll store some configuration in LocalStorage and then retrieve it following a page reload
Instructor: [00:01] This application allows a user to set the amount of results they want from a search query. If we look at the Redux store, the way it works is any changes on the select field produce an action called set config. In our store we have config per page that we set to the number that they select. It happens in this reducer.
[00:26] We have per page that starts with the default of 10 and responds to any set config actions, where the payload here can be any of these two keys. In our case just the select field sends through per page and then a number between 1 and 10.
[00:43] This is a nice feature, but if we reload the page you can see that we lost the number that was selected here. It would be nice if we could persist this configuration over page loads. We can use local storage for this, and it will be a great example of another case of composing data from different sources with Redux observable.
[01:03] The first thing to note is that we have this set config action. We can add a new epic. We're just going to call this persist. The first thing we'll do is listen for that set config action and then we'll use that as a trigger to store whatever is currently in the Redux store under the config key in local storage.
[01:26] We can export a function. We'll call this one assist epic. This takes a stream of actions and the state. We only care about the actions that have a type of set config. We'll call pipe and then we'll use of type from the Redux observable library. We'll bring in the set config constant. When the action occurs, we want to group that with the latest value from the state.
[02:01] We can use with latest from, pass along the state. We'll just pluck from that config. Then we can use the tap operator to get access to those values. We'll end up with an array here. We'll just import that. This will be the action and the second parameter will be the config. This is where we're going to perform the side effect and actually write something into local storage.
[02:35] Before we do anything there, let's not forget to ignore elements here. Since the purpose of this epic is just to listen for when this happens within the store, then retrieve the latest value of the config and do something with it. We don't actually want to produce any actions from this epic. We're just using it as a listener.
[03:02] Now we could just call local storage, set item, and we use a cache key. We'll just say Redux observable config. We'll just stringify that config. That's everything we need from this epic. We just need to go and register it with our combine epics.
[03:32] If we go back to configure store where we've registered this fetch beers epic, we'll add a second one in there and import that. We can go and test that in the browser now. Now if we go to the application panel and click on local storage and the address here, we see no values.
[03:54] If we change this to say four, we can see that we use that cache key and we set those two config items into local storage. So far so good. What happens if we reload the page. It goes back to 10. This value has persisted, but we're not using it to set the default value on page load. That's the next thing.
[04:19] Let's create another epic. This one we'll call hydrate. This will be responsible for reading the values from local storage once when the page loads and producing an action into the store to set those configuration values. If we say maybe config is local storage, get item.
[04:48] We'll use our cache key again. Then we'll check if the value we got back was actually a string. If it is a string, meaning the value that we set here, we can try to pass the JSON. We'll say passed, and we'll say JSON dot pass, maybe config. If that's successful, we'll return an observable of a single value which will be a call to the action creator set config. Pass along passed object. Import that.
[05:31] In the catch block if we do get an error, we can just return empty. Empty is an observable that doesn't produce any values. It just completes successfully. We can also return this if we don't make it inside that conditional. Now we need to register this again inside the configure store, pass it along here, and import it.
[05:57] Now this epic is just responsible for executing once. It produces an observable that will either have an action of set config or it will just be empty, not produce any values.
[06:11] Let's test it in the browser. We'll reload the page. Now we can see that the previous value of four automatically set this here. If we go to the Redux store, you can see that after the init we got this set config action which came from local storage. Any new values we set will persist also.