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.