【问题标题】:Redux + Persist + AsyncStorage return promise from dispatchRedux + Persist + AsyncStorage 从调度返回承诺
【发布时间】:2017-09-15 07:04:07
【问题描述】:

我的异步操作不是 http,它不使用 fetch api。那我该如何回报承诺。当我调度一个动作时,效果不是立竿见影的。我需要在完成操作后进行回调。我该怎么做?

这就是问题

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

我需要能够这样做

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

我正在使用redux-thunk 中间件。我也在使用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;

额外代码:

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

【问题讨论】:

    标签: reactjs react-native redux-thunk


    【解决方案1】:

    由于removeItem( id ) 是一个操作,该操作将从您的数据库/api/storage 中删除该项目。然后它必须发送另一个动作来表示它已经完成,如下所示:

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

    在你的 reducer 中,你现在将监听 ITEM_REMOVE_SUCCESITEM_REMOVE_FAIL 来改变你的状态。

    您不应该真正将业务逻辑放入组件中,因为这是不好的做法(即使 redux-thunk 可能允许您这样做)。

    如果您需要一个操作,首先删除该项目,然后,比如说,删除该项目的所有者,请创建一个复合函数:

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

    【讨论】:

    • 我正在使用 redux persist 将状态存储在移动设备上。它使用异步存储。没有 api/数据库。我已经更新了问题。
    【解决方案2】:

    您可以在 react native 中使用 Promise 来进行异步操作。例如:

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

    更新: 对于您的情况,它将如下所示:

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

    记得从removeItem返回resolve

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

    } 您可以在发生错误的情况下使用拒绝。

    【讨论】:

    • 您好,感谢您的回答。我想知道这是否可靠?设置超时?如果应用程序很慢并且超过了 250 毫秒怎么办?动作调度没有任何真正的回调吗?
    • 那是为了测试:)。如果您尝试我的代码,您会发现它打印出减少的数组长度。将 * setTimeout* 更改为 this.props.dispatch(removeItem(1));
    • 但要让它起作用,removeItem() 必须返回一个承诺,对吗?它没有。如何让它继续工作?
    • 我的错:),我没有注意到 removeItem 是一个 redux 操作。不需要返回callback(),直接调用即可。我刚刚编辑了答案,如果它不起作用,请随时添加评论。
    猜你喜欢
    • 2017-03-16
    • 2020-03-18
    • 2018-01-08
    • 2018-12-28
    • 1970-01-01
    • 2016-06-15
    • 2017-09-16
    • 2017-01-11
    • 2019-12-02
    相关资源
    最近更新 更多