React / Redux - 如何在第一个函数完成取出AJAX后调用componentDidMount中的第二个函数

时间:2018-02-28 03:22:01

标签: javascript reactjs ecmascript-6 redux axios

我有这个React-Native应用程序,它提取项目列表,然后是每个项目的图像库。基本上,我有两个ajax函数,第二个函数需要在第一个函数中获取的项目列表。 我在componentDidMount()中进行了第一次调用,但我不知道如何等待"为了完成第二次通话。如果我只是一个接一个地放置它们,第二个不会做任何事情,因为还没有物品清单。 我怎么解决这个问题?我在StackOverflow上阅读了类似的问题,但无法找到这个案例的明确例子。此外,在代码中,我评论了一些不成功的尝试。

在此先感谢,我是React的新手,所以我可能会错过一些简单的事情。

component.js

class EtiquetasList extends Component {

  componentDidMount() {
    this.props.FetchEtiquetas();
    if ( this.props.etiquetas.length > 0 ) { // I tried this but didn't do anything
      this.props.FetchGalleries( this.props.etiquetas );
    }
  }

  renderEtiquetas() {
      if ( this.props.galleries.length > 0 ) {
        // if I invoke FetchGalleries here, it works, but loops indefinitely
        return this.props.etiquetas.map(etiqueta =>
          <EtiquetaDetail key={etiqueta.id} etiqueta={etiqueta} galleries={ this.props.galleries } />
        );
      }
  }

  render() {
    return (
      <ScrollView>
        { this.renderEtiquetas() }
      </ScrollView>
    );

  }

}

const mapStateToProps = (state) => {
  return {
    etiquetas: state.data.etiquetas,
    isMounted: state.data.isMounted,
    galleries: state.slides.entries
  };
};

export default connect(mapStateToProps, { FetchEtiquetas, FetchGalleries })(EtiquetasList);

actions.js

export function FetchEtiquetas() {
  return function (dispatch) {
      axios.get( url )
        .then(response => {
          dispatch({ type: FETCH_ETIQUETAS_SUCCESS, payload: response.data })

        }
      );
  }
}

export function FetchGalleries( etiquetas ) {

    return function (dispatch) {
        return Promise.all(
          etiquetas.map( record =>
            axios.get('https://e.dgyd.com.ar/wp-json/wp/v2/media?_embed&parent='+record.id)
        )).then(galleries => {

          let curated_data = [];
          let data_json = '';

          galleries.map( record => {
            record.data.map( subrecord => {
              // this is simplified for this example, it works as intended
              data_json = data_json + '{ title: "' + subrecord.title+'"}';
          });

        my_data.push( data_json );

      });

          return dispatch({ type: FETCH_GALLERIES_SUCCESS, payload: curated_data });

        });
    }

}

reducer.js

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case FETCH_ETIQUETAS_SUCCESS:
      return { ...state, etiquetas: action.payload, isMounted: true }; // I think it ran faster like this tho
    default:
      return state;
  }
};

4 个答案:

答案 0 :(得分:1)

您可以尝试修改“获取”功能以返回Promise对象。然后你可以将它们链接起来像这样:

export function FetchEtiquetas() {
  return function (dispatch) {
      return axios.get( url ).then(response => {
        dispatch({ type: FETCH_ETIQUETAS_SUCCESS, payload: response.data }) 
      })
  }
}

在“componentDidMount”中调用:

this.props.FetchEtiquetas().then(() => {
  this.props.FetchGalleries( this.props.etiquetas );
})

答案 1 :(得分:0)

从您的代码中我假设您使用的是redux-thunk

我建议将它们组合成一个这样的动作创建者(在redux-thunk中可以):

export function FetchEtiquetasThenGalleries() {
  return function (dispatch) {
    axios.get(url)
      .then(response => {
        dispatch({ type: FETCH_ETIQUETAS_SUCCESS, payload: response.data })
        const etiquetas = response.data; // Assuming response.data is that array.
        return Promise.all(
          etiquetas.map(record =>
            axios.get('https://e.dgyd.com.ar/wp-json/wp/v2/media?_embed&parent=' + record.id)
          )).then(galleries => {

            let curated_data = [];
            let data_json = '';

            galleries.map(record => {
              record.data.map(subrecord => {
                // this is simplified for this example, it works as intended
                data_json = data_json + '{ title: "' + subrecord.title + '"}';
              });

              my_data.push(data_json);

            });

            dispatch({ type: FETCH_GALLERIES_SUCCESS, payload: curated_data });
          });
      });
  }
}

答案 2 :(得分:0)

componentWillReceiveProps(nextProps) {
 if(nextProps.etiquetas.length !== 0 && this.props.etiquetas.length === 0) {
   this.props.FetchGalleries( nextProps.etiquetas );
 }
}

我认为componentWillReceiveProps生命周期可以轻松完成工作。每当需要在反应组件的更新阶段触发某些内容时,您应该使用componentWillReceiveProps

答案 3 :(得分:0)

为了链接你的动作,如果可以,我建议链接Promise或使用async / await 要使用Promises执行此操作,您应该在操作中返回请求返回的Promise

export function FetchEtiquetas() {
  return function (dispatch) {
      return axios.get( url )
        .then(response => {
          dispatch({ type: FETCH_ETIQUETAS_SUCCESS, payload: response.data })

        }
      );
  }
}

在redux mapDispatchToProps调用中使用connect,它应该看起来像

function mapDispatchToProps(dispatch) {
    return {
     fetchData: () => {
         dispatch(FetchEtiquetas)
         .then((results) => {
             dispatch(FetchGalleries(results))
         });
      }
    }
}

然后在你的组件中,只需在componentDidMount

中调用正确的道具
componentDidMount() {
    this.props.fetchData();
}