Using Redux middleware for polling
In the frontend development world, we oftentimes need to have up-to-date data on the client. And to achieve that there are several options at our disposal:
- WebSockets (WS);
- Server-Sent Events (SSE);
- Polling (Short/Long).
While the first to are preferred, polling still is an important tool especially in situations when our backend can’t provide us with WS or SSE. And in this article, we will be reviewing how to use polling with arguably the most widely-used state manager in the JavaScript realm – Redux.
First things first – what polling is and how it’s done
There are two basic types of polling – Short and Long. For the sake of simplicity, we will be reviewing only Short polling. It’s the easiest one to implement – all it does – sends requests from the client-side to the server at a certain fixed interval. For example, let’s say we have a small website that shows the current weather in a selected region. And to keep the client up-to-date we can use the Short polling technique, that is, send client-to-server requests (for weather data) every 30 seconds. And, therefore, approximately (time between responses might differ) every 30 seconds we will be getting new weather data.
Now, let’s see how we can implement polling in React & Redux application. In our examples, we’ll continue working on the weather application and see how it can be realized using different techniques.
Setting the interval on the component mount
The most naive implementation would be by using the “setInterval” function in the “componentDidMount” method (or the “useEffect” hook).
In this implementation, we’re creating the “updateInterval” variable that points to an actual interval function after it’s being initialized in the “componentDidMount” life cycle method. The interval dispatches the “getWeatherData” redux-action every 30 seconds and does so continually while the component is mounted.
class WeatherApp extends Rect.Component { updateInterval; componentDidMount() { this.updateInterval = setInterval(() => { this.props.getWeatherData(); }, 1000 * 30); // 30 seconds } componentWillUnmount() { clearInterval(updateInterval); } render() { return ( <div> {this.props.weatherData} </div> ); } }
The biggest downside of this approach is that business logic (pulling data) is tight to the view. The other problem is that the “setInterval” function doesn’t wait till the previous action call (from the “setInterval” body) is completed. Therefore, this version can be improved by using the “setTimeout” function, with the help of which we can start each next cycle only when the previous one is completed. Thus, we won’t accidentally run into a situation where we have two (or even more) calls simultaneously (might happen in the case with “setInterval” on when we have small delays between cycles).
Here is our improved version with the use of the “setTimeout” function.
class WeatherApp extends React.Component { updateTimeout; componentDidMount() { this.getWeatherData(); } getWeatherData = async () => { await this.props.getWeatherData(); this.updateTimeout = setTimeout(this.getWeatherData, 30 * 1000); } componentWillUnmount() { clearTimeout(updateTimeout); } render() { return ( <div> {this.props.weatherData} </div> ); } }
We would like to point out that it’s not an actual code from production, just an example. And there is a good chance that async/await won’t be a viable option because the “getWeatherData” function most likely won’t be an asynchronous function – in such instances, we can use callbacks.
Nevertheless, even this improved version is still not good enough because we didn’t resolve the main problem – a tight connection between business logic and the presentation layer. And one of the drawbacks of previous solutions is that the update logic is defined in components thus making it hardly reusable.
Creating custom actions
By creating a custom action that will encapsulate all the “update by timeout” logic in action’s body – we can address the reusability drawback mentioned earlier and untight the connection between layers.
export const initActions = async dispatch => { let updateTimeout; getWeatherDataTimedout = async () => { await dispatch(getWeatherData()); updateTimeout = setTimeout(getWeatherDataTimedout, 30 * 1000); } /** Initialize any other actions */ getWeatherDataTimedout(); } class WeatherApp extends React.Component { componentDidMount() { this.props.initActions(); } render() { return ( <div> {this.props.weatherData} </div> ); } }
Again, it’s a simplified version. And the “initActions” function can be easily extended by adding custom parameters that can be passed from containers and by adding more actions that can be dispatched in the action’s body.
But we should look for another approach if we want to unentangle the “update by timeout” logic from the View as much as possible.
Middleware
One of the ways to achieve that level of disentanglement is to use Redux middlewares.
The concept is quite straightforward – middleware is some sort of a middleman between dispatching actions and actual execution of those same actions in the reducer.
With all that in mind, we can create a middleware for the “getWeatherData”:
const getWeatherDataTimedout = async dispatch => { await getWeatherData()(dispatch); setTimeout(() => updateMessages(dispatch), 30 * 1000); }; const getWeatherDataMiddleware = ({ dispatch }) => next => { getWeatherDataTimedout(dispatch); return action => next(action); };
But just creating middleware is not enough, it should be “registered” at the global store. To do so we can use the “compose” function inside of the “createStore” as follows:
const store = createStore( rootReducer, compose(applyMiddleware(/** other middlewares */, getWeatherDataMiddleware)) );
For more information and to develop web application using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
- medium.com
Don’t use async Redux middleware
Redux makes synchronous state updates explicit and reasonable, and makes visible the contract between React and the application: UI is a function of state, and it’s for this reason we’ll continue to use it.
But asynchronous effects are a whole other matter. we have variously used the middleware libraries Redux Thunk, Redux Loop and Redux Saga. Part-way through reading the Redux Observable documentation we started a clickbait Reddit thread and got pointed towards a better approach.
Before we go into that approach, here’s where we see problems with the leading async middleware libraries.
The problem with thunks
Using Redux Thunk mean having some of your action creators return async functions (thunks) that have access to dispatch()
, instead of plain objects.
Consider a typical async scenario — you want to grab something from an API and dispatch the response to the store. But you may also want to do other things with that API response — pop up a notification, say, or record some analytics to a 3rd party API.
If you incorporate those effects into your thunk, it will have some undesirable characteristics:
- it is now tightly bound to areas of your state it was previously unconcerned with
- your previously simple function is more bloated
- some of your async business logic, like analytics, gets spaghettified throughout unrelated thunks
- previously pure-object-returning actions now have to become thunks just to fire off async side effects
Not great. The problem with thunks is that they’re not powerful enough, not on their own.
The problem with sagas
Redux Saga allows you to define generator functions (sagas) that grab actions as they enter the store, perform whatever asynchronous actions they need, and dispatch()
resulting actions. They can also select
from the store.
This removes most of the problems exhibited above. By creating a showNotificationAfterApiResponse
saga that grabs the response action and updates some UI state, and a separate analyticsSaga
that grabs disparate actions to record events to your 3rd party analytics API, you can keep your original fetch-and-dispatch effect untouched.
However, sagas can do more than that. Being based around generators, they can pause their execution until certain conditions are met. They can also grab actions under certain conditions (just one action ever, or just the latest action, or take every action always). And this means sagas exhibit some different undesirable characteristics:
Generators are inherently stateful, so the effects that will be executed by your application do not solely depend on Redux state+action, but on the current state of this saga and any other saga that may get called by its operation
Generators are imperative, meaning anything other than the most simple cases can be challenging to grok
Generators are quite unusual syntactically, increasing the barrier to entry for new developers
In search of a better approach
It expanded on the Redux formula(state+action=new state) to include asynchronous side effects (state+action=new state+side effects). The library is avoided by a lot of developers as it seems to affect the purity of Redux reducers, but that’s a bit misleading: it doesn’t actually run the effects, it just returns what they will be.
As it turned out, we abandoned Redux Loop for other reasons — it does not play nice with other middleware (such as the wonderful Redux Persist), its syntax is fairly clunky, its uptake is low and falling — but the looped effect code had some properties that we found attractive:
It could take actions like sagas or epics without the async pollution experienced by thunks
It colocated async and synchronous effects, making it clear what responsibility each slice had for the side effects that were run
By keeping the switch (action.type)
mechanic, it resembled vanilla Redux, and so was more grokkable than generators or RxJS streams
“Why not write your own custom middleware?”
This was the sentence we read that forever changed the way I wrote async Redux. we hope to use it to convince you to change yours, too.
Vanilla Redux consists of 3 elements of boilerplate for each slice of state:
- Action types
- Action creators
- Reducer
Our approach adds a fourth:
- Custom middleware
Not every slice needs all four, though we find most do. Some slices just need the vanilla synchronous 3 elements, some (like analytics) only need the middleware element, and we have exotic cases that didn’t need state or a reducer, but just actions and the middleware to dispatch them.
In all cases, the pattern we use for custom middleware is this: alongside any userActions
and a userReducer
, we’ll add a userMiddleware
…
const userMiddleware = ({ getState, dispatch }) => next => async action => { const result = next(action); switch (action.type) { case SOME_ACTION: const asyncResult = await somethingAsync(); dispatch(anotherAction(asyncResult)); break; case SOME_OTHER_ACTION: const { slice: { stateVariable } } = getState(); await someProcess(stateVariable); break; } return Promise.resolve(result); }
Note how, when actions go in the top of the async function, they immediately get next(action)
-ed (passing them along to the next middleware or the destination store), and then there’s a switch (action.type)
with case
s that perform the side effects before the promised result is resolved (which allows your dispatch()
es to be await
ed).
And this is what we love about this pattern: the asynchronous middleware closely resembles a synchronous reducer. Just as the reducer is pure in that a given action on a given state will always produces the same resultant state, the middleware has its own purity: a given action on a given state will always run the same effects.
This makes async effects easy to understand. It has given up the power of the saga (it now can only take every action of a type) but in doing so has simplified it and made tracking your side effects obvious.
For more Information and to build a website using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft“.To develop your custom website using React JS, please visit our technology page.
Content Source:
- medium.com
React Apollo vs Redux + REST: Implementing the same feature twice
Why we had to do the same feature twice
Because of the way things have evolved in Wix, we have separate developers working on web and mobile. In mobile we are using React Native, so theoretically the same person could work on both platforms. But that isn’t the case now. As time went by, web and mobile developers used different stacks for their modules. One of the modules is using Redux with Axios REST calls on the web while the mobile part is using React Apollo. Moreover, both web and mobile use their own middleware servers to communicate with backend servers. That means that every time we want to implement something we have to do the same work twice. This is hurting our development velocity. So I’ve decided to see how much work it would take to reduce the amount of duplication that we do. To do that we had to see how both web and mobile are working right now.

photo courtesy of medium.com
Feature Explanation
The feature that we had to develop overall was quite simple. we had to enable editing an order. That includes:
- Creating an Edit Order form.
- Adding a button in the order overview screen which opens the edit order form.
- Adding logic to decide when the button should be displayed.
- Finally sending updated data to the server and updating the order overview with new info.
Data Loading
One of the first issues that we had to solve was implementing logic whether the loader should be displayed when opening edit form or not. The user might open the form from other page and have all the data loaded or he might go to the form directly. That meant that with Redux we had to call multiple selectors and check that all relevant form is loaded. That form is loaded through multiple rest calls and saved into multiple reducers, so for this code, we had to write unit tests since it was complex.
const loadOneRestCall = () => async (dispatch) => { const data = await api.loadData(); dispatch(setData(data)); } ... export const loadEditOrderIfNecessary = (orderId) => async (dispatch, getState) => { if (!selectors.getComplexSelectorShouldLoad(getState(), orderId)) { return; } await Promise.all([ dispatch(loadOneRestCall()), dispatch(loadSecondRestCall()), ]).then(() => { dispatch(setEditOrderFormLoaded()); }); } EditOrder.actions.js
class EditOrderComponent extends React.PureComponent { componentDidMount() { this.props.dispatch(actions.loadEditOrderIfNecessary(this.props.orderId)); } render() { if (this.props.loading) { return <Loader/>; } return ( <Form data={this.props.data} /> ); } } const mapStateToProps = (state) => { return { data: editOrderSelector.getFormData(state), loading: editOrderSelector.isLoading(state), }; }; export const EditOrder = connect(mapStateToProps)(EditOrderComponent); EditOrder.component.jsx
With React Apollo we didn’t have to think about this at all. React Apollo made sure that if we have the necessary data in the cache it won’t make any additional network calls, but if we don’t, we can just show the loader. All of this is easy to do because data loading is written declaratively. Because this part is so trivial we didn’t have to write any unit tests for it.
const EDIT_ORDER_QUERY = gql` query EditOrderQuery(orderId: ID!) { order(id: $orderId) { ...Order } } `; class EditOrderComponent extends React.PureComponent { render() { return ( <Query query={EDIT_ORDER_QUERY} variables={{orderId: this.props.orderId}}> {(data, loading) => { if (loading) { return <Loader/>; } return ( <Form data={data}/> ); }} </Query> ); } } EditOrder.component.jsx
Calling the API
Calling the API both with Redux and React Apollo is quite simple. With Redux we emit an action which gets the data out of the store and then calls an API service. With React Apollo we write a mutation query inside the component, and then directly call it inside the component. Once again the amount of code with React Apollo is smaller but personally, we don’t like the way you have to write mutations with it. It gets quite messy when you have multiple mutations in one place. React Apollo should get hook support some time in the future, so that should simplify it.
... render() { return ( <Mutation onError={this.onError1} mutation={MUTATION1}> {(mutation1) => ( <Mutation onError={this.onError2} mutation={MUTATION2}> {(mutation2) => ( <Mutation onError={this.onError3} mutation={MUTATION3}> {(mutation3) => { return ( <View mutation1={mutation1}, mutation2={mutation2}, mutation3={mutation3}/> ); }} </Mutation> )} </Mutation> )} </Mutation> ); } render.jsx
Updating the local state
After updating the order we have to make sure that the data that we display is correct. With Redux that means updating the state inside the reducer. Once again there are some moving parts here, so to feel safe we write unit tests for it.
React Apollo takes care of it completely. Because the returned order has an ID, it will override newly returned data inside its cache. That once again is so trivial that we don’t have to write any unit tests for it (if you want to read more about React Apollo cache you can do it here).
One thing we have to mention is that with Redux, it feels easier to update the state when you create a new item inside the list. With React Apollo you would have to write a query to get the data out of the cache, then update the data and then write new data on top of that query.
const cached = readQuery(cache, {query: QUERY, variables}); writeQuery( cache, { query: QUERY, data: { orders: [order].concat(cached ? cached.orders : []), }, variables, }, ); cache.js
Usually, the code above scares new people when data becomes more complex.
E2E test
Whenever we implement a feature we always write an e2e test for it.
In mobile, we use Detox while on the web we use Puppeteer. The way tests are written is quite different, but what really matters here is how we mock our server calls.
With GraphQL we start a mock server with mocked resolvers. Because GraphQL enforces you to write correct queries, we are quite confident that the things we mock in our tests represent real-life scenarios.
it('should edit order', () => { const order1 = new orderBuilder().build(); server.setQuery({ order: () => order1, }); server.setMutation({ editOrder: (_, variables) => { return { ...order1, ...variables, }; }, }); // ...do the test, check that the view is updated with new info after calling edit order. }); test.e2e.js
If you are using REST the situation becomes more difficult. You have to mock REST calls but there is no good way to enforce that what you mock is going to be true. So even though you may have passing E2E tests you may still get production issues. Another solution is to start the whole server when running E2E tests, but that brings a lot of additional moving parts that can get flaky and writing tests becomes a lot more difficult.
Typescript and IDE support
When you are working on a bigger project Typescript becomes a really important part for it. But writing Typescript means having to write more code. And we really don’t like typing a lot. For us, the best coding experience is the one when we can have as much code completion as possible.
Both web and mobile parts of the project are using Typescript. To have proper type checking on Redux we have to write manually the types for actions and payloads, then we have mappings between actions and reducers. When you are typing action names you don’t get any auto completion. When you are creating an interface for that action type once again you don’t get any autocompletion. we think you understand where we were heading.
GraphQL, on the other hand, has type generation (Apollo Tooling). Also, both WebStorm and VS Code have plugins for GraphQL which include autocompletion for your queries. That significantly reduces the amount of manual typing you have to do. And having types allows you to easily jump around the whole project.
Redux benefits
The comparison wouldn’t be fair if we didn’t give any benefits to the Redux. In my opinion, the main Redux benefit is that we know that it works and we know that it works well. We can assume that we can easily explain to new people how Redux works. It brings a lot of boilerplate but it doesn’t hide any magic inside itself. If you want to have more flavor in Redux there are libraries that can bring it to you. There are libraries that enable less verbose code, add integrations with other libraries and many other things. Redux is just really popular and you know that if you need something you can find it.
React Apollo brings a lot of overhead. It works great while it works. But as soon as you start hitting bumps you are up for a tough time. we can expect new people to get into cases where they can get lost or React Apollo starts to break for what looks like no reason. There are quite a lot of open issues in Github. And usually, new people that we hire don’t have any experience with it.
How we are planning to reduce the amount of work
Implementing this feature twice was needed to see how much similarities and differences we have between web and mobile. Moving forward one thing that is really clear is that we need to use one middleware server instead of two. And here GraphQL is a clear winner. GraphQL allows customizing our queries for web and mobile without having to create separate endpoints for it. Also, it simplifies our e2e tests because we don’t have to start a real server anymore.
We don’t think we are going to remove Redux from the web. That would require us to waste a lot of time without implementing new things.
For more Information and to build a website using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft“.To develop your custom website using React JS, please visit our technology page.
Content Source:
- medium.com
Using Reselect Selectors for Encapsulation and Performance with Redux
An overview of why and how to use Reselect with React and Redux
In a good Redux architecture, you are encouraged to keep your store state minimal, and derive data from the state as needed. As part of that process, we recommend that you use “selector functions” in your application, and use the Reselect library to help create those selectors. Here’s a depth detail of correct use of Reselect.
Basics of Selectors
A “selector function” is simply any function that accepts the Redux store state (or part of the state) as an argument, and returns data that is based on that state. Selectors don’t have to be written using a special library, and it doesn’t matter whether you write them as arrow functions or the function
keyword. For example, these are all selectors:
const selectEntities = state => state.entities; function selectItemIds(state) { return state.items.map(item => item.id); } const selectSomeSpecificField = state => state.some.deeply.nested.field; function selectItemsWhoseNamesStartWith(items, namePrefix) { const filteredItems = items.filter(item => item.name.startsWith(namePrefix)); return filteredItems; }
You can call your selector functions whatever you want, but it’s common to prefix them with select
or get
, or end the name with Selector, like selectFoo
, getFoo
, or fooSelector
.
The first reason to use selector functions is for encapsulation and reusability.
Reselect Usage and Memoization
The next reason to use selectors is to improve performance. Performance optimization generally involves doing work faster, or finding ways to do less work. For a React-Redux app, selectors can help us do less work in a couple different ways.
Let’s imagine that we have a component that requires a very expensive filtering/sorting/transformation step for the data it needs. To start with, its mapState
function looks like this:
const mapState = (state) => { const {someData} = state; const filteredData = expensiveFiltering(someData); const sortedData = expensiveSorting(filteredData); const transformedData = expensiveTransformation(sortedData); return {data : transformedData}; }
Right now, that expensive logic will re-run for every dispatched action that results in a state update, even if the store state that was changed was in a part of the state tree that this component doesn’t care about.
What we really want is to only re-run these expensive steps if state.someData
has actually changed. This is where the idea of “memoization” comes in.
Memoization is a form of caching. It involves tracking inputs to a function, and storing the inputs and the results for later reference. If a function is called with the same inputs as before, the function can skip doing the actual work, and return the same result it generated the last time it received those input values.
The Reselect library provides a way to create memoized selector functions. Reselect’s createSelector
function accepts one or more “input selector” functions, and an “output selector” function, and returns a new selector function for you to use.
const selectA = state => state.a; const selectB = state => state.b; const selectC = state => state.c; const selectABC = createSelector( [selectA, selectB, selectC], (a, b, c) => { // do something with a, b, and c, and return a result return a + b + c; } ); // Call the selector function and get a result const abc = selectABC(state); // could also be written as separate arguments, and works exactly the same const selectABC2 = createSelector( selectA, selectB, selectC, (a, b, c) => { // do something with a, b, and c, and return a result return a + b + c; } );
Advanced Optimizations with React-Redux
There’s a specific performance issue that can occur when you use memoized selectors with a component that can be rendered multiple times.
The React-Redux connect
function supports a special “factory function” syntax for mapState
and mapDispatch
functions, which can be used to create unique instances of selector functions for each component instance.
If the first call to a mapState
or mapDispatch
function returns a function instead of an object, connect
will use that returned function as the real mapState
or mapDispatch
function. This gives you the ability to create component-instance-specific selectors inside the closure:
const makeUniqueSelectorInstance = () => createSelector( [selectItems, selectItemId], (items, itemId) => items[itemId] ); const makeMapState = (state) => { const selectItemForThisComponent = makeUniqueSelectorInstance(); return function realMapState(state, ownProps) { const item = selectItemForThisComponent(state, ownProps.itemId); return {item}; } }; export default connect(makeMapState)(SomeComponent);
Both component 1 and component 2 will get their own unique copies of selectItemForThisComponent
, and each copy will get called with consistently repeatable inputs, allowing proper memoization.
Hire React.js Developer from us, as we give you high quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft“.
To develop custom web app using React.js, please visit our technology page.
Content Source:
- blog.isquaredsoftware.com