REACT 如何使用 Redux 和 Axios(使用 promise 中间件)发出 AJAX 请求?
REACT How to make AJAX requests with Redux and Axios (with promise middleware)?
我有这个动作创建器:
export function getLevelsMap() {
const request = axios.get(`/api/levels`);
return {
type: GET_LEVELS_MAP,
payload: request
}
}
和这个减速器
import { GET_LEVELS_MAP } from '../actions';
export default function (state = null, action) {
switch (action.type) {
case GET_LEVELS_MAP:
return action.payload.levels;
default:
return state;
}
}
AJAX 请求应该 return 我这个 :
{
"levels": [
{
"_id": "5951b7f0600af549fb1d269a",
"name": "College",
"__v": 0,
"subjects": [
{
"_id": "594891db1dbdf635ca3019ab",
"name": "Maths",
"__v": 0
},
{
"_id": "5948920d1dbdf635ca3019ac",
"name": "Biology",
"__v": 0
}
...
请求确实有效(我用 PostMan 测试过)
现在,我将我的组件与减速器和动作连接起来:
function mapStateToProps(state) {
return {
levels: state.levels
}
};
export default connect(mapStateToProps, { getLevelsMap })(ChooseSubject);
我正在 componentDidMount 方法中获取数据(调用操作):
componentDidMount() {
if (!this.props.levels) {
this.props.getLevelsMap();
}
}
并尝试使用减速器:
getSubjects(level) {
let levels = this.props.levels;
if (levels) {
for (var item of levels) {
if (item.name === level) {
return item;
}
}
}
return null;
}
这是我声明我正在使用 promise 中间件的地方
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<Switch>
<Route path="/" component={HomePage} />
</Switch>
</BrowserRouter>
</Provider>
, document.querySelector('.root'));
但是,this.props.levels 未定义...
PS:如果我对 AJAX 请求的答案进行硬编码(复制粘贴我从 postMan 得到的结果到 subjects_reducer),一切正常。
非常感谢您的帮助:)
您不是在等待 axios 完成调用。首先,我假设 applyMiddleware
内部的 promise
类似于 redux-thunk,您将需要它来执行异步操作。
您的动作创建器应如下所示:
export const getLevelsMap = () => {
return function(dispatch) {
axios.get(`/api/levels`)
.then(result => {
dispatch({
type: GET_LEVELS_MAP,
payload: result.data
});
})
.catch(err => console.log(err));
}
}
或者,使用异步和等待:
export const getLevelsMap = () => async dispatch => {
try {
let response = await axios.get(`/api/levels`);
dispatch({
type: GET_LEVELS_MAP,
payload: result.data
})
} catch (err) {
console.log(err);
}
}
如之前的回答所述,您的 axios 请求返回的是承诺而不是数据,您所拥有的是未解决的承诺,因此导致您的道具不是您所期望的。
为了回答您的问题,我认为您不需要使用 redux-promise,而是使用 redux-thunk。基于 答案,似乎 redux-promise 允许您的操作成为承诺,但 redux-thunk 允许您的操作成为您需要的功能。使用 redux-thunk,您实际上能够解决承诺并将数据发送到您的减速器,这与现在您的减速器刚刚获得承诺不同。
我有这个动作创建器:
export function getLevelsMap() {
const request = axios.get(`/api/levels`);
return {
type: GET_LEVELS_MAP,
payload: request
}
}
和这个减速器
import { GET_LEVELS_MAP } from '../actions';
export default function (state = null, action) {
switch (action.type) {
case GET_LEVELS_MAP:
return action.payload.levels;
default:
return state;
}
}
AJAX 请求应该 return 我这个 :
{
"levels": [
{
"_id": "5951b7f0600af549fb1d269a",
"name": "College",
"__v": 0,
"subjects": [
{
"_id": "594891db1dbdf635ca3019ab",
"name": "Maths",
"__v": 0
},
{
"_id": "5948920d1dbdf635ca3019ac",
"name": "Biology",
"__v": 0
}
...
请求确实有效(我用 PostMan 测试过)
现在,我将我的组件与减速器和动作连接起来:
function mapStateToProps(state) {
return {
levels: state.levels
}
};
export default connect(mapStateToProps, { getLevelsMap })(ChooseSubject);
我正在 componentDidMount 方法中获取数据(调用操作):
componentDidMount() {
if (!this.props.levels) {
this.props.getLevelsMap();
}
}
并尝试使用减速器:
getSubjects(level) {
let levels = this.props.levels;
if (levels) {
for (var item of levels) {
if (item.name === level) {
return item;
}
}
}
return null;
}
这是我声明我正在使用 promise 中间件的地方
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<Switch>
<Route path="/" component={HomePage} />
</Switch>
</BrowserRouter>
</Provider>
, document.querySelector('.root'));
但是,this.props.levels 未定义... PS:如果我对 AJAX 请求的答案进行硬编码(复制粘贴我从 postMan 得到的结果到 subjects_reducer),一切正常。
非常感谢您的帮助:)
您不是在等待 axios 完成调用。首先,我假设 applyMiddleware
内部的 promise
类似于 redux-thunk,您将需要它来执行异步操作。
您的动作创建器应如下所示:
export const getLevelsMap = () => {
return function(dispatch) {
axios.get(`/api/levels`)
.then(result => {
dispatch({
type: GET_LEVELS_MAP,
payload: result.data
});
})
.catch(err => console.log(err));
}
}
或者,使用异步和等待:
export const getLevelsMap = () => async dispatch => {
try {
let response = await axios.get(`/api/levels`);
dispatch({
type: GET_LEVELS_MAP,
payload: result.data
})
} catch (err) {
console.log(err);
}
}
如之前的回答所述,您的 axios 请求返回的是承诺而不是数据,您所拥有的是未解决的承诺,因此导致您的道具不是您所期望的。
为了回答您的问题,我认为您不需要使用 redux-promise,而是使用 redux-thunk。基于