J'ai un React App, je dois passer un appel ajax (pour apprendre) à un service en ligne (asynchrone) avec Redux.
Ceci est mon magasin:
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import duedates from './reducers/duedates'
export default applyMiddleware(thunk)(createStore)(duedates);
Ce sont les actions:
import rest from '../Utils/rest';
export function getDueDatesOptimistic(dueDates){
console.log("FINISH FETCH");
console.log(dueDates);
return {
type: 'getDueDate',
dueDates
}
}
export function waiting() {
console.log("IN WAIT");
return {
type: 'waiting'
}
}
function fetchDueDates() {
console.log("IN FETCH");
return rest({method: 'GET', path: '/api/dueDates'});
}
export function getDueDates(dispatch) {
console.log("IN ACTION");
return fetchDueDates().done(
dueDates => dispatch(getDueDatesOptimistic(dueDates.entity._embedded.dueDates))
)
}
Et voici le réducteur:
export default (state = {}, action) => {
switch(action.type) {
case 'getDueDate':
console.log("IN REDUCER")
return state.dueDates = action.dueDates;
default:
return state
}
}
Je ne comprends pas ce que je fais mal. L'action est appelée parfaitement à partir du composant. Mais alors je reçois cette erreur:
Erreur: Les actions doivent être des objets simples. Utilisez un middleware personnalisé pour les actions asynchrones.
Je suppose que j'utilise mal le middleware react-thunk. Qu'est-ce que je fais mal?
EDIT
Maintenant, l'action appelle le réducteur, mais le réducteur, après avoir changé d'état, ne réexécute pas la méthode de rendu.
case 'getDueDate':
console.log("IN REDUCER")
return state.dueDates = action.dueDates;
Je pense que vous devriez utiliser la fonction compose
, donc c'est comme
import {
createStore,
applyMiddleware,
compose
} from 'redux';
import thunk from 'redux-thunk';
import duedates from './reducers/duedates'
export default compose(applyMiddleware(thunk))(createStore)(duedates);
Thunk permet à un créateur d’action de renvoyer une fonction au lieu d’un objet simple. Vous l’utilisez donc comme
export function getDueDates() {
return dispatch => {
console.log("IN ACTION");
fetchDueDates().done(
dueDates => dispatch(getDueDatesOptimistic(dueDates.entity._embedded.dueDates))
)
};
}
Vous retourniez un objet Promise, c'était une partie du problème. Une autre partie est que redux-thunk n'a pas été correctement appliqué. Je parie que compose
devrait résoudre le problème.
La réponse acceptée est soit dépassée, soit erronée, soit trop compliquée. Voici la documentation sur le sujet de composition:
http://redux.js.org/docs/api/compose.html
afin que nous puissions le faire comme ceci à la place:
import {createStore, combineReducers, compose, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
const reducer = combineReducers({
user: userReducer,
items: itemsReducer
});
// here is our redux-store
const store = createStore(reducer,
compose(applyMiddleware(thunk))
);
Je crois qu’il est possible d’avoir une solution opérationnelle sans utiliser aussi la fonction compose
. Basé sur la documentation du repo GitHub pour redux-thunk
La solution fonctionne pour redux-thunk: ^2.0.0
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import duedates from './reducers/duedates'
export function configureStore(initialState = {}) {
return createStore(
duedates,
initialState,
applyMiddleware(thunk)
);
}