Instructor: Instead of having this API URL hardcoded in this file like this, let's have it as part of our store. If we create a new reducer, we'll call it config. We'll just have some initial state where there's an API base being that URL and then our actual reducer, which at the moment isn't responding to any actions but rather is just allowing us to have this state accessible.
We need to go to our configure store file and register that reducer. We'll add it here. Config, config reducer. Now we'll be able to access this from within our epic. If we come back here, this little search helper that we have should now accept also an API base like that. Here where we're calling the search helper, we need to get the value from the store.
The way we do that inside our epics is we take the second parameter which is an observable of state. If it's a static value like a URL that's never going to change, you're probably safe just to say state or value. Then you can access config and the API base.
If we remove this delay and check it still works in the browser, you can see it does. State.value is a property added to this observable by the Redux Observable library. It gives us access to the entire store.
That's why we have to access.config here, because when we configured the store, we said all of the state under the config reducer lives on the config property. That's why we can access API base, because that comes from here.
This is one way of accessing state within your epics, but it's not the best way. The main problem with accessing state like this is you've now tightly coupled this callback here with the outer environment because you can no longer execute this without this state variable being in scope.
That means if you wanted to refactor this code and pull this large function body out in a separate file or a separate function, you're not going to have to pass along the state as well. Really, what we want to be able to do is access both the action and the state like that. If we could do that, it removes the coupling of the outer scope.
We can use with latest from, which is an operator from our RX that takes an observable and when its source observable-being this action stream here-emits a value, it will group that value together with the last value that came from this state here.
That's why we get an array here and we have to destructure it. This part being the original action from the stream above it. The second element being the value emitted from this observable.
What that means is we can remove this and just say state. Check again in the browser and we get the same result. Another reason that I always recommend using this approach rather than the value directly is that because this is just an observable, we can do all the normal things we can do with composition.
Imagine that we want to test this function in isolation. For this state object, we would have to construct an object that had a config object and then an API based property. If all we use in here is this string that comes from here, we could remove this pot by doing this.
We could pluck config and then API base. Pluck is an operator that will try to access properties on objects or arrays based on the keys you give it here. Now we can change this to being just API base. We're limiting the scope of what our function actually needs. That is going to work exactly the same.
It's a tiny bit more work to use this style, but the benefits are endless. Especially when you realize that with latest from can take any number of observables. You may pull that apart from the store and you may have some other element in the store like a user and you could pull in their auth token. That would then be accessible to you here.
The point here is we're taking multiple data sources and we're using composition to collate just the bits we need for each function.