redux-thunk
1.在创建strore的时候注册redux-thunk中间件。
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
const store = createStore(reducers, applyMiddleware(thunk));
2.使用redux-thunk
//正常发送一个action,但是dispatch中传入的是一个函数,函数中执行异步操作
store.dispatch(getList());
//getList函数
const getList = () => {
return (dispatch) => {
new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 300);
}).then(() => {
dispatch({
type: 'addList',
payload: [4, 5, 6],
});
});
};
};
不使用redux-thunk中间件的时候,dispatch只能发送javascrip对象,使用之后可以发送一个函数,函数会获取一个dispatch对象,使用这个对象和不使用中间件的时候一样。
redux异步处理方案
useEffect 异步操作问题
如果在响应回来之前组件被销毁了会怎样?
问题的核心在于,在组件卸载后依然调用了 setValue(data.value)和 setLoading(false)来更改状态。因此一个简单的办法是标记一下组件有没有被卸载,可以利用 useEffect的返回值。
useEffect( => {
let isUnmounted = false;
(async => {
const res = await fetch(SOME_API);
const data = await res.json;
if (!isUnmounted) {
setValue(data.value);
setLoading(false);
}
});
return => {
isUnmounted = true;
}
}, []);
AbortController中断请求:
useEffect( => {
let isUnmounted = false;
const abortController = new AbortController; // 创建
(async => {
const res = await fetch(SOME_API, {
singal: abortController.singal, // 当做信号量传入
});
const data = await res.json;
if (!isUnmounted) {
setValue(data.value);
setLoading(false);
}
});
return => {
isUnmounted = true;
abortController.abort; // 在组件卸载时中断
}
}, []);
singal实现中断异步请求:
import React, { Component } from 'react';
import axios from 'axios';
class Example extends Component {
signal = axios.CancelToken.source();
state = {
isLoading: false,
user: {},
}
componentDidMount() {
this.onLoadUser();
}
componentWillUnmount() {
this.signal.cancel('Api is being canceled');
}
onLoadUser = async () => {
try {
this.setState({ isLoading: true });
const response = await axios.get('https://randomuser.me/api/', {
cancelToken: this.signal.token,
})
this.setState({ user: response.data, isLoading: true });
} catch (err) {
if (axios.isCancel(err)) {
console.log('Error: ', err.message); // => prints: Api is being canceled
} else {
this.setState({ isLoading: false });
}
}
}
render() {
return (
<div>
<pre>{JSON.stringify(this.state.user, null, 2)}</pre>
</div>
)
}
}