2016-02-20 32 views
22

Ho un'app React, ho bisogno di fare una chiamata ajax (per imparare) a un servizio online (async) con Redux.Azioni asincrone in Redux

Questo è il mio negozio:

import { createStore, applyMiddleware } from 'redux'; 
import thunk from 'redux-thunk'; 
import duedates from './reducers/duedates' 


export default applyMiddleware(thunk)(createStore)(duedates); 

Si tratta di azioni:

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)) 
    ) 
} 

e questo è il riduttore:

export default (state = {}, action) => { 
    switch(action.type) { 
    case 'getDueDate': 
     console.log("IN REDUCER") 

     return state.dueDates = action.dueDates; 
    default: 
     return state 
    } 
} 

non ottengo quello che sto facendo male . L'azione viene chiamata perfettamente dal componente. Ma ottengo questo errore:

Error: Actions must be plain objects. Use custom middleware for async actions.

Suppongo che sto usando male il middleware react-thunk. Cosa sto sbagliando?

EDIT

Ora l'azione sta chiamando al riduttore, ma il riduttore, dopo aver cambiato lo stato, non è ri-eseguire il metodo Render

case 'getDueDate': 
     console.log("IN REDUCER") 

     return state.dueDates = action.dueDates; 

risposta

24

Credo che si dovrebbe usare compose funzione, quindi è come

Thunk consente a un creatore di azioni di restituire una funzione invece di ain-oggetto, in modo da utilizzarlo come

export function getDueDates() { 
    return dispatch => { 
    console.log("IN ACTION"); 
    fetchDueDates().done(
     dueDates => dispatch(getDueDatesOptimistic(dueDates.entity._embedded.dueDates)) 
    ) 
    }; 
} 

Si stavano tornando un oggetto di promessa, che è stata una parte del problema. Un'altra parte era che redux-thunk non è stato applicato correttamente. Scommetto che compose dovrebbe risolvere il problema.

+0

Grande, sembra funzionare ora. ma nel riduttore, quando restituisco lo stato 'return state.dueDates = action.dueDates;', non chiama di nuovo il rendering .. Devo aggiungere qualcos'altro? – Pablo

+0

Al momento, nell'esempio di codice, entrambe le azioni non cambiano stato. Si restituisce lo stato stesso. Puoi aggiornare le tue domande in modo che io (o chiunque altro) possa vedere la situazione attuale? –

+0

aggiornato, ora I 'return state.dueDates = action.dueDates;' – Pablo

11

La risposta accettata è obsoleta, errata o eccessivamente convoluta. Qui ci sono i documenti sulla composizione soggetto:

http://redux.js.org/docs/api/compose.html

in modo che possiamo fare in questo modo, invece:

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)) 
); 
0

Credo che è possibile avere una soluzione di lavoro senza utilizzare la funzione compose troppo . Sulla base della documentazione dalla repo GitHub per redux-thunk

soluzione funziona per 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) 
); 
} 
+0

Ehi, Kevin, ma da dove proviene 'createReducer'? –

+0

HI @RishatMuhametshin, ho corretto l'esempio sopra. 'createReducer' era una funzione per evitare il codice boilerplate e preso da [react-boilerplate] (https://github.com/react-boilerplate/react-boilerplate/blob/master/app/reducers.js) –

Problemi correlati