在调用另一个动作创建者之前等待动作创建者完成 - Redux thunk
Wait for action creator to finish before calling another action creator - Redux thunk
我的应用程序中有 2 个动作创建器,分别称为 createPlaylist 和 fillPlaylist,为了调用 fillPlaylist,我必须先调用 createPlaylist 以获取播放列表的 ID(state.playlistDetail.id in fillPlaylist)。问题是当我调用 fillPlaylist 时,createPlaylist 仍在获取数据,所以我无法调用 fillPlaylist,因为 state.playlistDetail.id 未定义。我想等到 createPlaylist 完成请求然后调用 fillPlaylist,我该如何实现?
创建播放列表
export const createPlaylist = () => async (dispatch, getState) => {
const state = getState()
let uris = []
const data = JSON.stringify({
'name': 'Playlist Name',
'description': 'Playlist description',
})
const response = await spotify.post(`/users/${state.user.id}/playlists`, data, {
'headers' : {
'Authorization': 'Bearer ' + state.token,
'Content-Type': 'application/json'
},
})
dispatch({type: 'CREATE_PLAYLIST', payload: response.data})
}
填充播放列表
export const fillPlaylist = (uris) => async (dispatch, getState) => {
const state = getState()
const data = JSON.stringify({
'uris': uris
})
console.log('state.playlistDetail', state)
const response = await spotify.post(`/playlists/${state.playlistDetail.id}/tracks`, data, {
'headers' : {
'Authorization': 'Bearer ' + state.token,
'Content-Type': 'application/json'
},
})
dispatch({type: 'FILL_PLAYLIST', payload: response.data})
}
结果组件(这是我调用 createPlaylist 和 fillPlaylist 的地方)
import React, {Component} from 'react';
import { connect } from 'react-redux';
import { createPlaylist, fillPlaylist } from '../actions'
class Result extends Component {
constructor(props) {
super(props);
this.state = {}
}
createPlaylist = () => {
this.props.createPlaylist()
let uris = []
this.props.recommendations.forEach(item => {
uris.push(item.uri)
})
this.props.fillPlaylist(uris)
}
render() {
return (
<div>
<h1>Result</h1>
<button onClick={this.createPlaylist}>Create Playlist</button>
</div>
);
}
}
const mapStateToProps = state => {
return {recommendations: state.recommendations};
};
export default connect(mapStateToProps, {createPlaylist, fillPlaylist})(Result);
既然你在使用 react-redux,你有没有研究过 redux-sagas 中间件?它在管理数据获取等副作用方面非常有帮助,有点像可以启动和停止的单独线程,并在数据返回后触发其他操作 (sagas)。
我已经使用 redux-thunk 和 redux-sagas 来帮助解决您遇到的这个问题。 Redux-sagas 得到了我工作的咨询公司的高级开发人员的高度推荐,现在已经使用了两次,我不得不说我绝对喜欢它!
你说你需要等待 createPlaylist
完成获取数据,那么为什么不像这样将 2 个函数合并为一个:
export const createAndFillPlaylist = () => async (dispatch, getState) => {
try {
const state = getState();
let uris = state.recommendations.map(item => item.uri);
const PlayListBody = JSON.stringify({
name: "Playlist Name",
description: "Playlist description"
});
const headers = {
Authorization: "Bearer " + state.token,
"Content-Type": "application/json"
};
const { data } = await spotify.post(
`/users/${state.user.id}/playlists`,
PlayListBody,
{ headers }
);
dispatch({ type: "CREATE_PLAYLIST", payload: data });
const createPlaylistBody = JSON.stringify({
uris: uris
});
const response = await spotify.post(
`/playlists/${data.id}/tracks`,
createPlaylistBody,
{
headers
}
);
dispatch({ type: "FILL_PLAYLIST", payload: response.data });
} catch (error) {
throw error;
}
};
对于不需要的组件 ToMapStateToProps
,代码如下:
import React, { Component } from "react";
import { connect } from "react-redux";
import { createAndFillPlayList } from "../actions";
class Result extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<h1>Result</h1>
<button onClick={this.props.createAndFillPlayList}>
Create Playlist
</button>
</div>
);
}
}
export default connect(
null,
{ createAndFillPlayList }
)(Result);
我的应用程序中有 2 个动作创建器,分别称为 createPlaylist 和 fillPlaylist,为了调用 fillPlaylist,我必须先调用 createPlaylist 以获取播放列表的 ID(state.playlistDetail.id in fillPlaylist)。问题是当我调用 fillPlaylist 时,createPlaylist 仍在获取数据,所以我无法调用 fillPlaylist,因为 state.playlistDetail.id 未定义。我想等到 createPlaylist 完成请求然后调用 fillPlaylist,我该如何实现?
创建播放列表
export const createPlaylist = () => async (dispatch, getState) => {
const state = getState()
let uris = []
const data = JSON.stringify({
'name': 'Playlist Name',
'description': 'Playlist description',
})
const response = await spotify.post(`/users/${state.user.id}/playlists`, data, {
'headers' : {
'Authorization': 'Bearer ' + state.token,
'Content-Type': 'application/json'
},
})
dispatch({type: 'CREATE_PLAYLIST', payload: response.data})
}
填充播放列表
export const fillPlaylist = (uris) => async (dispatch, getState) => {
const state = getState()
const data = JSON.stringify({
'uris': uris
})
console.log('state.playlistDetail', state)
const response = await spotify.post(`/playlists/${state.playlistDetail.id}/tracks`, data, {
'headers' : {
'Authorization': 'Bearer ' + state.token,
'Content-Type': 'application/json'
},
})
dispatch({type: 'FILL_PLAYLIST', payload: response.data})
}
结果组件(这是我调用 createPlaylist 和 fillPlaylist 的地方)
import React, {Component} from 'react';
import { connect } from 'react-redux';
import { createPlaylist, fillPlaylist } from '../actions'
class Result extends Component {
constructor(props) {
super(props);
this.state = {}
}
createPlaylist = () => {
this.props.createPlaylist()
let uris = []
this.props.recommendations.forEach(item => {
uris.push(item.uri)
})
this.props.fillPlaylist(uris)
}
render() {
return (
<div>
<h1>Result</h1>
<button onClick={this.createPlaylist}>Create Playlist</button>
</div>
);
}
}
const mapStateToProps = state => {
return {recommendations: state.recommendations};
};
export default connect(mapStateToProps, {createPlaylist, fillPlaylist})(Result);
既然你在使用 react-redux,你有没有研究过 redux-sagas 中间件?它在管理数据获取等副作用方面非常有帮助,有点像可以启动和停止的单独线程,并在数据返回后触发其他操作 (sagas)。
我已经使用 redux-thunk 和 redux-sagas 来帮助解决您遇到的这个问题。 Redux-sagas 得到了我工作的咨询公司的高级开发人员的高度推荐,现在已经使用了两次,我不得不说我绝对喜欢它!
你说你需要等待 createPlaylist
完成获取数据,那么为什么不像这样将 2 个函数合并为一个:
export const createAndFillPlaylist = () => async (dispatch, getState) => {
try {
const state = getState();
let uris = state.recommendations.map(item => item.uri);
const PlayListBody = JSON.stringify({
name: "Playlist Name",
description: "Playlist description"
});
const headers = {
Authorization: "Bearer " + state.token,
"Content-Type": "application/json"
};
const { data } = await spotify.post(
`/users/${state.user.id}/playlists`,
PlayListBody,
{ headers }
);
dispatch({ type: "CREATE_PLAYLIST", payload: data });
const createPlaylistBody = JSON.stringify({
uris: uris
});
const response = await spotify.post(
`/playlists/${data.id}/tracks`,
createPlaylistBody,
{
headers
}
);
dispatch({ type: "FILL_PLAYLIST", payload: response.data });
} catch (error) {
throw error;
}
};
对于不需要的组件 ToMapStateToProps
,代码如下:
import React, { Component } from "react";
import { connect } from "react-redux";
import { createAndFillPlayList } from "../actions";
class Result extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<h1>Result</h1>
<button onClick={this.props.createAndFillPlayList}>
Create Playlist
</button>
</div>
);
}
}
export default connect(
null,
{ createAndFillPlayList }
)(Result);