Изменение статуса загрузки после получения данных полностью
У меня есть создатель действий для получения данных из API и другой создатель действий для загрузки статуса и я хочу изменить статус загрузки, когда данные полностью извлечены.
Теперь я написал следующие коды, но они не работают должным образом. Состояние загрузки изменяется на false до того, как данные будут полностью получены.
Мой ActionCreator:
export const loadingStatus = (bool) => {
return {
type: Constants.LOADING_STATUS,
isLoading: bool
};
}
const allFlashCards = (action) => {
return{
type: Constants.ALL_CARD,
...action
}
};
export const fetchAllFlashCards = () => {
return (dispatch) => {
dispatch(loadingStatus(true));
return axios.post(API.DISPLAY_ALL_CARDS)
.then((data)=>{
console.warn(data);
dispatch(allFlashCards(data));
dispatch(loadingStatus(false));
}).catch((error)=>{
console.warn(error)
});
}
};
и мой редуктор:
const FlashCard = (state = [], action) => {
switch (action.type) {
case Constants.ADD_CARD:
return {...state, data: action.data};
break;
case Constants.ALL_CARD:
return {...state, data: action};
break;
default:
return state;
}
};
export const Loading = (status= false, action) => {
switch (action.type) {
case Constants.LOADING_STATUS:
return action.isLoading;
break;
default:
return status;
}
}
и в моем компоненте:
componentDidMount() {
this.props.fetchCards();
}
render() {
return(
<div>
{this.props.loading ?
<Loading/> :
Object.keys(this.props.cards.data).map(this.renderCard)
}
</div>
);
}
const mapStateToProps = (state) => ({
cards: state.main,
loading: state.loading
});
const mapDispatchToProps = (dispatch) => ({
fetchCards: bindActionCreators(fetchAllFlashCards, dispatch)
});
и объединить редуктор это:
import { combineReducers } from 'redux';
import FlashCard , { Loading } from './FlashCard.js';
import { routerReducer } from "react-router-redux";
export default combineReducers({
main: FlashCard,
loading: Loading,
routing: routerReducer
});
На моей странице у меня есть ошибка в консоли, и это:Uncaught TypeError: Cannot read property 'data' of undefined
и если положить мои коды в тайм-аут, исправил мою ошибку:/
Что я должен делать?
2 ответа
Наконец я исправил свою проблему:
В моем actionCreator измените метод fetchAllFlashCards следующим образом:
export const fetchAllFlashCards = () => {
return (dispatch) => {
dispatch(loadingStatus(true));
return axios.post(API.DISPLAY_ALL_CARDS)
.then(({data})=>{
dispatch(allFlashCards(data));
dispatch(loadingStatus(false));
}).catch((error)=>{
console.warn(error)
});
}
};
а в редукторе поменяй редуктор FlashCard на следующий:
const FlashCard = (state = [], action) => {
switch (action.type) {
case Constants.ADD_CARD:
return {...state, data: action.data};
break;
case Constants.ALL_CARD:
return {...state, data: action.data};
break;
default:
return state;
}
};
Ваше состояние по умолчанию здесь неверно:
const FlashCard = (state = [], action) => {
switch (action.type) {
case Constants.ADD_CARD:
return {...state, data: action.data};
break;
case Constants.ALL_CARD:
return {...state, data: action};
break;
default:
return state;
}
};
Это должен быть пустой объект {}
вместо пустого массива []
, так как вы возвращаете объекты.
Этот код
export const fetchAllFlashCards = () => {
return (dispatch) => {
dispatch(loadingStatus(true));
return axios.post(API.DISPLAY_ALL_CARDS)
.then((data)=>{
console.warn(data);
dispatch(allFlashCards(data));
dispatch(loadingStatus(false));
}).catch((error)=>{
console.warn(error)
});
}
};
Выглядит совершенно нормально. loadingStatus(false)
Не следует вызывать перед установкой флэш-карт. Ваши редукторы и создатели действий синхронны (как и должно быть). Так что ничего особенного там нет.
Я видел, что вы используете action.data
на Constants.ADD_CARD
действие, но в вашем коде вы не отправляете никаких действий с этим типом. Вы делаете это где-нибудь еще? Может быть в этом и ошибка?
РЕДАКТИРОВАТЬ:
Другое место, которое вы используете .data
находится в вашем рендерере: this.props.cards.data
, Какова ценность state.main
? Как вы создаете свой rootReducer? Это должно быть что-то вроде этого:
const rootReducer = combineReducers({
main: FlashCard,
loading: Loading,
});
Ты используешь main
там? Или, может быть cards
?