Our Global Presence
Canada
57 Sherway St,
Stoney Creek, ON
L8J 0J3
India
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
USA
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
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:
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.
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.
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.
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.
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:
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
© 2024 — HK Infosoft. All Rights Reserved.
© 2024 — HK Infosoft. All Rights Reserved.
T&C | Privacy Policy | Sitemap