0
votes

My async action is not http, it doesn't use fetch api. How do i return a promise then. When i dispatch an action, the effect is not immediate. I need to do a callback after it completes the action. How do i do this?

this is the problem

console.log(this.props.items.length); // 5
this.props.dispatch(removeItem(1));
console.log(this.props.items.length); // 5

i need to be able to do it like this

this.props.dispatch(removeItem(1))
    .then(() => this.props.dispatch(anotherAction()));

i am using the redux-thunk middleware. i am also using AsyncStorage & redux-persist

store.js

import { compose, createStore, applyMiddleware } from 'redux';
import { persistStore, autoRehydrate } from 'redux-persist';
import thunk from 'redux-thunk';
import reducers from '../reducers';
import { AsyncStorage } from 'react-native';
import createLogger from 'redux-logger';

const logger = createLogger({
  predicate: () => process.env.NODE_ENV === 'development'
});

const middleWare = [ thunk, logger ];

const createStoreWithMiddleware = applyMiddleware(...middleWare)(createStore);

export function makeStore(onComplete :? () => void) {
  const store = autoRehydrate()(createStoreWithMiddleware)(reducers);
  persistStore(store, {
    storage: AsyncStorage
  }, onComplete);
  return store;
}

export default makeStore;

extra code:

function removeItem(id) {
    return {
        type: 'REMOVE_ITEM',
        id
    }
}
2

2 Answers

0
votes

since removeItem( id ) is an action, that action will remove the item from your database/api/storage. It will then have to dispatch another action to say it is done, like this:

function removeItemSuccess( id ) {
    return { type: 'ITEM_REMOVE_SUCCESS', payload: id });
}
function removeItemFail( error ) {
    return { type: 'ITEM_REMOVE_FAIL', payload: error });
}
function removeItem ( id ) {
    return (dispatch) => {
        dispatch({type: 'ITEM_REMOVE'}); // put this in an action
        return request.delete('/item/'+id).then(() => {
            dispatch( removeItemSuccess(id) );
        }).catch((err) => {
            dispatch( removeItemFail(err) );
        });
    }
}

in your reducer, you will now listen for ITEM_REMOVE_SUCCES or ITEM_REMOVE_FAIL to mutate your state.

You shouldn't really put the business-logic in your components since it's bad practice (even if redux-thunk allows you to, possibly).

If you need an action that first removes the item and then, let's say, removes to owner of that item, make a compound function:

function removeItemAndOwner( itemId ) {
    return (dispatch) => {
        dispatch(removeItem(itemId))
        .then((item) => {
            return dispatch(removeOwner(item.ownerId))
        });
    }
}
0
votes

you can use Promise in react native to make async actions. For example:

let test=[0,1,2];
console.log(test.length);
let myFirstPromise = new Promise((resolve, reject) => {
  setTimeout(function(){
    test.splice(1);
    resolve(); 
  }, 250);
});

myFirstPromise.then(() => {
  console.log( test.length);
});

Update: For your case it will be something like below:

console.log(this.props.items.length); // 5
let myFirstPromise = new Promise((resolve, reject) => {
  this.props.dispatch(removeItem(1, resolve));
});

myFirstPromise.then(() => {
  console.log(this.props.items.length); // 4
});

remember to return the resolve from removeItem:

function removeItem(id, callback) {
callback();
return {
    type: 'REMOVE_ITEM',
    id
 }

} you can use reject for the case of error happening.