score:1

so this needs a very basic introduction to the flow of redux with 'side effects'.

the redux flow

  1. [view]your view reacts in various ways.
  2. [actions]we create an abstraction over these reactions called 'actions'.
  3. [dispatcher] this actions are dispatched to the store.
  4. [reducer] in the store we have logic written in 'reducers' that look at the actions and do manipulations to the store to update the store state.
  5. [state]this state is loaded on the react state tree.

definition alert! in redux stuff like calls to apis are called side effects. this is because you are doing something outside the typical unidirectional data flow.

enter image description here

hope you have understood this flow. i'm specifically concerned about a specific part that you seem to be confused about. so in your code you have tried to do this.

 then(response => {
     return dispatch(getaddress()); 
 })

what your code is trying to do here is that, it's trying to 'dispatch' a side effect. this is wrong!

dispatch is almost always a plain old js object which is serializable. typically you will have stereotypical structure like this. which you seem to have in your other get address call.

{ 
    type: 'get_address_request_success', 
    payload: {} 
}

so the proper way to approach your task is like this. think of dispatching actions like emitting signals when various things happen.

export const login = (value, history) => dispatch => {
    axios.post('/api/users/login', value)
        .then(response => {
            //send out a success signal
            dispatch({
                type: 'loginsuccess',
                payload: response.data
            });

            //now that i have logged in successfully i can call for my address
            //this is simply how you call an action within an action!
            getaddress();
        }).catch(error => {
            //login failed signal
            dispatch({
                type: 'loginfailed',
                payload: response
            }); // i am calling like this
        });
}

export const getaddress = () => dispatch => {
    axios.get('/api/address')
        .then(response => {
            //get address success signal
            dispatch({
                type: 'getaddresssuccess',
                payload: response.data
            });
        }).catch(function (error) {
            //get addresses failed signal
            dispatch({
                type: 'getaddressfailed',
                payload: error
            }); 
        });
}

the next important part is the reducer, which you have not included here! if actions emits signals think of the reducers as a receiver which receives and processes this signal. a reducer will update the existing state based on the action deployed.

export default function appreducer(state, action) {
    switch (action.type) {
        case 'getaddresssuccess': //waiting on the signal!
            return object.assign({},state,{address : action.payload} 
            //set the proper address based on your payload from the api call

        default:
            return state

    }
}

you also should have setup your redux thunk configuration properly for this to fully work. cheers!

============edit=============

so upon checking the codebase, you have used the combine reducer to meld multiple reducers together.

import { combinereducers } from 'redux';
import authreducer from './authreducer';
import addressreducer from './addressreducer';

const rootreducer = combinereducers({
  authreducer,
  addressreducer
});

export default rootreducer;

so in mapsstatetoprops your store state will look like this

{
  authreducer: {
    // state managed by the authreducer 
  },
  addressreducer: {
    address: 'test streat, london'
  }
}

so change your mapstatetoprops to look like this

const mapstatetoprops = state => ({
  addresses: state.addressreducer.address
});

export default connect(mapstatetoprops)(dashboard);

score:3

redux thunk middleware allows to chain via dispatch, dispatch(...) returns dispatched action, i.e. a promise if promise chains weren't broken:

export const login = (value, history) => dispatch => {
    return axios.post('/api/users/login', value) // return!
    .then(response => {
        return dispatch(getaddress()); // return!
    })
    .catch(error => {});
}

export const getaddress = () => dispatch => {
    return axios.get('/api/address') // return!
    .then(response => {
        return dispatch({ // return!
            type: 'getaddresses',
            payload: response.data
        });
    })
    .catch(function (error) {});
}

initial action should be dispatched somewhere. in vanilla redux setup, it could be dispatched after store definition:

store.dispatch(login());

in react redux setup, components are integral parts of redux data flow. asynchronous thunk is a side effect and it should be dispatched once in componentdidmount. in case of initial action, it should be dispatched in parent component:

@connect()
class app extends component {
  componentdidmount() {
    return this.props.dispatch(login());
  }

  render() {
    return !this.props.addresses ? 'loading' :  <dashboard />
  }
}

here is a demo.


Related Query

More Query from same tag