React Redux 在另一个 action 之后 dispatch action

29

我有一个异步动作,它从REST API中获取数据:

export const list = (top, skip) => dispatch => {
    dispatch({ type: 'LIST.REQUEST' });

    $.get(API_URL, { top: top, skip: skip })
        .done((data, testStatus, jqXHR) => {
            dispatch({ type: 'LIST.SUCCESS', data: data });
        });
};

更改 skip 状态的 异步 操作:

export const setSkip = (skip) => {
    return {
        type: 'LIST.SET_SKIP',
        skip: skip
    };
};

top = 10, skip = 0是组件的初始状态。

class List extends Component {
    componentDidMount() {        
        this.list();
    }

    nextPage() {
        let top = this.props.list.top;
        let skip = this.props.list.skip;

        // After this 
        this.props.onSetSkip(skip + top);

        // Here skip has previous value of 0.
        this.list();
        // Here skip has new value of 10.
    }

    list() {
        this.props.List(this.props.list.top, this.props.list.skip);
    }

    render () {
        return (
            <div>
                <table> ... </table>
                <button onClick={this.nextPage.bind(this)}>Next</button>
            </div>
        );
    }
}

当首次点击按钮下一页(Next)时,使用异步操作的skip的值不会改变。 我该如何在同步(sync)操作后分发动作?


Redux Saga是为了解决这种问题而开发的,请参见此答案 - Sid Ali
5个回答

15

如果您正在使用redux thunk,您可以轻松地将它们组合起来。

它是一种中间件,允许操作创建者返回一个函数而不是一个操作。

如果您不需要链接动作创建者并且只需要运行它们两个,则您的解决方案现在可能已经起作用。

this.props.onList(top, newSkip);
this.props.onSetSkip(newSkip);

如果您需要将它们链接起来(以同步方式调用它们)或等待第一个已调度的操作的数据,则我建议使用以下方法。
export function onList(data) {
  return (dispatch) => {
          dispatch(ONLIST_REQUEST());
    return (AsyncAPICall)
    .then((response) => {
      dispatch(ONLIST_SUCCESS(response.data));
    })
    .catch((err) => {
      console.log(err);
    });
  };
}

export function setSkip(data) {
      return (dispatch) => {
              dispatch(SETSKIP_REQUEST());
        return (AsyncAPICall(data))
        .then((response) => {
          dispatch(SETSKIP_SUCCESS(response.data));
        })
        .catch((err) => {
          console.log(err);
        });
      };
    }

export function onListAndSetSkip(dataForOnList) {
  return (dispatch) => {
     dispatch(onList(dataForOnList)).then((dataAfterOnList) => {
       dispatch(setSkip(dataAfterOnList));
     });
  };
}

6

在同步操作之后,您是否可以直接从reducer调用函数,而不是调度一个action?

因此,它遵循以下流程:

同步操作调用--> Reducer调用 ---> case函数(reducer)---> case函数(reducer)

而不是通常的流程,对于您来说可能是这样的:

同步操作调用--> Reducer调用

请按照此指南拆分reducers,以查看case reducers是什么。

但是,如果您想要调度的操作具有副作用,则正确的方法是使用Thunks,然后您可以在操作后调度操作。

Thunks示例:

export const setSkip = (skip) => {
    return (dispatch, getState) => {

        dispatch(someFunc());
        //Do someFunc first then this action, use getState() for currentState if you want
        return {
            type: 'LIST.SET_SKIP',
            skip: skip
        };
    }
};

谢谢您的帮助。您能提供一些示例代码吗?(我是React的新手) - Denis Bednov
如果你按照thunks指南操作,那么thunks应该对你有用。无论如何,按照我链接的指南将你的reducers分开,你就会明白我在说什么了。 - Martin Dawson

1

0

谢谢回复,但我是这样做的:

let top = this.props.list.top;
let skip = this.props.list.skip;
let newSkip = skip + top;

this.props.onList(top, newSkip);
this.props.onSetSkip(newSkip);

首先我计算新的skip,并使用这个新值分派一个异步操作。然后我分派一个同步操作,更新状态中的skip


-1

dispatch({ type: 'LIST.SUCCESS', data: data, skip: 同步操作后所需的值 });


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接