在调用另一个动作创建者之前等待动作创建者完成 - Redux thunk

Posted

技术标签:

【中文标题】在调用另一个动作创建者之前等待动作创建者完成 - Redux thunk【英文标题】:Wait for action creator to finish before calling another action creator - Redux thunk 【发布时间】:2020-11-21 22:35:57 【问题描述】:

我的应用中有 2 个动作创建者,分别称为 createPlaylist 和 fillPlaylist,为了调用 fillPlaylist,我必须先调用 createPlaylist 以获取播放列表的 id(fillPlaylist 中的 state.playlistDetail.id)。问题是当我调用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);

【问题讨论】:

【参考方案1】:

您说您需要等待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】:

由于您使用的是 react-redux,您是否研究过 redux-sagas 中间件?它在管理诸如数据获取之类的副作用方面非常有帮助,就像一个可以启动和停止的单独线程,并在您的数据返回后触发其他操作(sagas)。

我已经使用了 redux-thunk 和 redux-sagas 来帮助解决您遇到的这个问题。 Redux-sagas 得到了我工作的咨询公司的高级开发人员的强烈推荐,现在已经使用了两次,我不得不说我绝对喜欢它!

https://redux-saga.js.org/

【讨论】:

以上是关于在调用另一个动作创建者之前等待动作创建者完成 - Redux thunk的主要内容,如果未能解决你的问题,请参考以下文章

如何键入 Redux thunk 动作创建者以返回承诺

登录方法在推送路由之前不等待调度动作完成

如何在 redux-saga 中等待另一个动作

如何等待递归直到函数完成执行

Thunk 动作创建者派出另一个 thunk 动作创建者,但 typescript 抛出错误。我应该添加啥类型?

如何在 Haxe 中创建动作脚本对象