如何从react / redux

时间:2019-11-15 18:52:33

标签: javascript reactjs asynchronous redux axios

我正在开发我的第一个react / redux Web应用程序,该应用程序从外部api获取音乐会。我的动作创建者中有几个与此相关的动作,包括"LOADING_CONCERTS", "GET_CONCERTS", AND "SET_CONCERTS"。然后,在“音乐会列表”组件中渲染这些音乐会。在redux处于加载动作时,是否可以添加加载栏组件以进行渲染?一些代码:

我的异步axios:

export const getConcerts = (artist) => {
      return (dispatch) => {
        dispatch({ type: 'LOADING_CONCERTS' });
        return axios.get(${api_url})
          .then(concerts => {
            dispatch({ type: 'GET_CONCERTS', concerts })
            dispatch({ type: 'SET_CONCERTS', concerts })
            dispatch(addReviewsToConcerts(concerts))
          })
          .catch( err=> {
            console.log(err.code)
            console.log(err.message)
            console.log(err.stack)
          }
          )
        }
    }

我的减速器:

const initialState = []

export default (state = initialState, action) => {
  switch (action.type) {
    case 'LOADING_CONCERTS':
      return state;
    case 'GET_CONCERTS':
      return action.concerts.data
    case 'ADD_REVIEWS_TO_CONCERTS':
      return action.concerts
    case 'SAVE_CONCERT':
      return action
    default:
      return state;
  }
}

音乐会容器:


import React from 'react';
import ConcertSearchFormWrapper from './ConcertSearchFormWrapper';
import ConcertsList from '../.././components/concerts/ConcertsList';
import { connect } from 'react-redux';

const Concerts = (props) => {
    return (
      <div className="concerts-container">
        <ConcertSearchFormWrapper />
        { (props.concerts.length > 0 && props.concerts !== '\n{warn=Not found}\n') ? <ConcertsList /> : null}
      </div>
    )
};

export default connect((state) => ({ concerts: state.concerts })) (Concerts);

,然后是列表组件:

import React from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { withRouter } from 'react-router-dom'
import { saveConcert } from '../.././actions/concerts/concerts'




const ConcertsList = ({concerts, saveConcert}) => {

    const date = (datetime) => {
      return new Date(datetime).toDateString()
    }

    return (

      <div className = "concerts-list">

        {concerts.sort((a, b) => (a.datetime < b.datetime) ? 1 : -1).map(c => <><Link key={c.id} to={`/concerts/${c.id}`}  onClick={()=>saveConcert(c)}>{c.lineup[0]} at {c.venue.name} on {date(c.datetime)}</Link><br/></>)}
      </div> 
    )
}



const mapStateToProps = (state, ownProps) => {
  return {

      concerts: state.concerts
  }
}

export default withRouter(connect(mapStateToProps, {saveConcert})(ConcertsList))

1 个答案:

答案 0 :(得分:1)

这是如何添加加载微调器或加载栏

  1. 更新您的原始状态以包括放置指示器(例如'isLoading'布尔值。

const initialState = { isLoading: false, concerts: [], reviews: [] };

  1. 更改案件陈述以正确更新每个操作的状态,以下大致是我的操作方法
const concertReducer = (state = initialState, action) => {
  switch (action.type) {
    case "LOADING_CONCERTS":
      return { ...state, isLoading: true };
    case "GET_CONCERTS":
      return { ...state,
               concerts: action.payload,
               isLoading: false };
    case "ADD_REVIEWS_TO_CONCERTS":
      return { ...state,
              reviews: action.payload };

    default:
      return state;
  }
};

export default concertReducer;

3. bring in the isLoading prop to your component using connect and mapStateToProps
4. use ternary operator to check if 'isLoading' is true and conditionally render your spinner or loading bar as follows 

 {props.isLoading ? (
                <YourLoadinBarHere' />
              ) : (
                <Component or something to render when isLoading is false/>
              )}
now, your loading bar will be displayed while the data is fetching ('isLoading' is true)
of course there are other solutions like using HOC pattern but this is how I usually do it.