Why do we specifically deal with asynchry? Because the design principle of Redux requires that our reducer must be a pure function, so it is illegal for us to perform some side effects on reducer. So what about asynchrony? I don’t think dealing with asynchrony is too difficult for developers who really understand Redux. If you don’t have an in-depth understanding of Redux and its middleware mechanisms, the following may cause some discomfort and confusion, so I recommend reading my first article on how to re-engineer Redux from 0 to 1

redux-thunk

Take a look at the source code

function createThunkMiddleware(extraArgument) { return ({ dispatch, GetState}) => next => action => { If (typeof Action === 'function') {return action(dispatch, getState, dispatch); extraArgument); } return next(action); }; }Copy the code

The principle is simple: Dispatch can dispatch not only the original action, but also the function. Middleware Thunk discovers that the action is a function and hands over all the core methods and parameters. See how it works in practice

Import fetch from 'fetch' export function fetchNews(id) {// Thunk Middleware knows how to handle functions. // Here we pass the dispatch method as an argument to the function so that it can dispatch the action itself. Return function (dispatch) {// Dispatch: Update your application's state to inform // Thunk Middleware that calls to functions can have a return value, and // it will be passed as a return value from the Dispatch method. // In this case, we return a promise waiting to be processed. // It's not necessary for Redux Middleware, but it's handy. return fetch(`/api/getNews`, {id}) .then( response => response.json(), error => console.log('An error occurred.', error) ) .then(json => dispatch({ name: 'add_news', data: json }) ) } }Copy the code

Put asynchronous business into redux

const store = createStore( rootReducer, applyMiddleware( thunkMiddleware, FetchNews (1)).then(() => console.log(store.getState()))Copy the code

In this way, we can easily solve the problem of Redux not supporting asynchrony by encapsulating the asynchronous business and handing it to ReUDx’s Dispatch as an asynchronous action. Is there a better asynchronous solution? Going back to Redux and the asynchronous business itself, the most critical and straightforward point is that in asynchrony a business can be dispatched, and any solution to redux asynchrony can solve the problem if this requirement is met.

Promise. Then with the store

See directly

Store export const store = createStore(rootReducer)Copy the code
// business module
import * as React from 'react';
import './index.less';
import {store} from './redux'

class Header extends React.Component {
  constructor(props: LogoProps) {
    super(props);
  }
  
  componentDidMount() {
    fetch(`/api/getNews`, {id: 1})
      .then(
        response => response.json(),
         error => console.log('An error occurred.', error)
      )
      .then(json =>
         store.dispatch({
             name:  'add_news',
             data: json
         })
      )
  }
  
  render() {
    return (<div>
      hello world
    </div>);
  }
}

export default Header;
Copy the code

This makes it easy for middleware to handle asyncio without the need for middleware, but this is not good for code management, as we can aggregate each asynchronous business module by module.

Async/awit and BaseAction

Start by creating a base class that encapsulates the Store’s Dispatch

import {store} from './redux'; export default class ActionModeBase { dispatch(params) { store.dispatch(params); }}Copy the code

Create another class that handles the request news business

import BaseAction from './ActionModeBase';
import fetch from 'fetch'
export default class HandleNewsMode {
	getNews = async (id) => {
    	const news = await fetch('/api/getNews', id);
        this.dispatch({
            name: 'add_news',
            data: news
        })
    }
}
Copy the code

The business side introduces classes for asynchronous business

import * as React from 'react'; import './index.less'; import HandleNewsMode from './HandleNewsMode' class Header extends React.Component { constructor(props: LogoProps) { super(props); BusinessMode = new HandleNewsMode(); // Initialize this.businessMode = new HandleNewsMode(); } componentDidMount() { this.businessMode.getNews(1); } render() { return (<div> hello world </div>); }Copy the code

conclusion

Redux-thunk is not a panacea. For more complex asynchronous scenarios, I think cohesive asynchronous business + Async is more competent.