最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to call callback function after dispatch action Redux - Stack Overflow

programmeradmin1浏览0评论

I use React Redux and I create a function to login, but I need to get a callback return after successfull login and redirect user to a page.

I try to passing function as parameter but not working.

How can I get the return after dispatch action?

Login fun
export const login = (request,cb) => {
           return dispatch => {
                let url = "/api/user/login";
                axios({
                    method: "post",
                    url: url,
                    data: request,
                    config: { headers: { "Content-Type": "multipart/form-data" } }
                })
                    .then(response => {
                        let authState = {
                            isLoggedIn: true,
                            user: response.data
                        };
                        cb();
                        window.localStorage["authState"] = JSON.stringify(authState);
                        return dispatch({
                            type: "USER_LOGIN_FULFILLED",
                            payload: { userAuthData: response.data }
                        });
                    })
                    .catch(err => {
                        return dispatch({
                            type: "USER_LOGIN_REJECTED",
                            payload: err
                        });
                    });
           };
    };

submiting

handleLogin(e) {
        this.setState({ showLoader: true });
        e.preventDefault();
        const request = new Object();
        if (this.validator.allValid()) {
            request.email = this.state.email;
            request.password = this.state.password;
            this.props.login(request, () => {
                //get callbach here
                this.props.history.push('/my-space/my_views');
            })

            this.setState({ showLoader: false });

        } else {
            this.setState({ showLoader: false });
            this.validator.showMessages();
            this.forceUpdate();
        }
    }
const mapStateToProps = state => {
    return {
        authState: state
    };
};
const mapDispatchToProps = dispatch => {
    return {
        login: request => dispatch(login(request))
    };
};
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);

I use React Redux and I create a function to login, but I need to get a callback return after successfull login and redirect user to a page.

I try to passing function as parameter but not working.

How can I get the return after dispatch action?

Login fun
export const login = (request,cb) => {
           return dispatch => {
                let url = "/api/user/login";
                axios({
                    method: "post",
                    url: url,
                    data: request,
                    config: { headers: { "Content-Type": "multipart/form-data" } }
                })
                    .then(response => {
                        let authState = {
                            isLoggedIn: true,
                            user: response.data
                        };
                        cb();
                        window.localStorage["authState"] = JSON.stringify(authState);
                        return dispatch({
                            type: "USER_LOGIN_FULFILLED",
                            payload: { userAuthData: response.data }
                        });
                    })
                    .catch(err => {
                        return dispatch({
                            type: "USER_LOGIN_REJECTED",
                            payload: err
                        });
                    });
           };
    };

submiting

handleLogin(e) {
        this.setState({ showLoader: true });
        e.preventDefault();
        const request = new Object();
        if (this.validator.allValid()) {
            request.email = this.state.email;
            request.password = this.state.password;
            this.props.login(request, () => {
                //get callbach here
                this.props.history.push('/my-space/my_views');
            })

            this.setState({ showLoader: false });

        } else {
            this.setState({ showLoader: false });
            this.validator.showMessages();
            this.forceUpdate();
        }
    }
const mapStateToProps = state => {
    return {
        authState: state
    };
};
const mapDispatchToProps = dispatch => {
    return {
        login: request => dispatch(login(request))
    };
};
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
Share Improve this question edited Jan 9, 2020 at 2:22 ranieribt 1,3061 gold badge15 silver badges33 bronze badges asked Jan 8, 2020 at 15:32 Boutamente abdessamadBoutamente abdessamad 5732 gold badges11 silver badges34 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 2

The cb is missing in your connect(...)

Here is the fix

handleLogin(e) {
        this.setState({ showLoader: true });
        e.preventDefault();
        const request = new Object();
        if (this.validator.allValid()) {
            request.email = this.state.email;
            request.password = this.state.password;
            this.props.login(request, () => {
                //get callbach here
                this.props.history.push('/my-space/my_views');
            })

            this.setState({ showLoader: false });

        } else {
            this.setState({ showLoader: false });
            this.validator.showMessages();
            this.forceUpdate();
        }
    }
const mapStateToProps = state => {
    return {
        authState: state
    };
};
const mapDispatchToProps = dispatch => {
    return {
        login: (request, cb) => dispatch(login(request, cb))
    };
};
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);

Hope it helps:)

If you are using redux-thunk, you can return a Promise from your async action.

The function called by the thunk middleware can return a value,
that is passed on as the return value of the dispatch method.
In this case, we return a promise to wait for.
This is not required by thunk middleware, but it is convenient for us.

But I prefer use useEffect or ponentDidUpdate for this purpose:

ponentDidUpdate(){
  if(this.props.authState.isLoggedIn){
    this.props.history.push('/my-space/my_views');  
  }
}

I remend using the Redux Cool package if you need actions with callback capability.

Instalation

npm install redux-cool

Usage

import {actionsCreator} from "redux-cool"


const my_callback = () => {
    console.log("Hello, I am callback!!!")
}

const callbackable_action = actionsCreator.CALLBACKABLE.EXAMPLE(1, 2, 3, my_callback)

console.log(callbackable_action)
//      {
//          type: "CALLBACKABLE/EXAMPLE",
//          args: [1, 2, 3],
//          cb: f() my_callback,
//          _index: 1
//      }

callbackable_action.cb()
//      "Hello, I am callback!!!"

When we try to generate an action object, we can pass the callback function as the last argument. actionsCreator will check and if the last argument is a function, it will be considered as a callback function.

See Actions Creator for more details

react-redux/redux dispatch returns a promise. you can do this if you want to return a value or identify if the request is success/error after being dispatched

Action example

export const fetchSomething = () => async (dispatch) => {
    try {
        const response = await fetchFromApi();
        dispatch({
            type: ACTION_TYPE,
            payload: response.value
        });
        return Promise.resolve(response.value);
    } catch (error) {
        return Promise.reject(error);
    }
}

Usage

const foo = async data => {
    const response = new Promise((resolve, reject) => {
        dispatch(fetchSomething())
            .then(v => resolve(v)) 
            .catch(err => reject(err)) 
    });
    await response 
        .then((v) => navigateToSomewhere("/", { replace: true }))
        .catch(err => console.log(err));
};

this post is old, but hopefully it will help

Package.json

   "react-redux": "^8.0.2"
   "@reduxjs/toolkit": "^1.8.5"

How about sending callback function as parameter to action creator? It works for my login logic.

ponent:

  // inside the ponent
  const loginCallback = () => {
    history.push(location.state.referrer);
  };

  const handleLogin = (loginData) => {
    dispatch(loginActionCreator(loginData, loginCallback));
  };

action creator:

// inside the action creator

export const loginActionCreator =
  (loginData, loginCallback) => (dispatch, getState) => {
    dispatch({
      type: userActions.setFetchState,
      payload: FETCH_STATES.FETCHING,
    });
    doSRRequest(srEndpoints.login(loginData))
      .then((res) => {
        dispatch({
          type: userActions.setUser,
          payload: res,
        });
        dispatch({
          type: userActions.setFetchState,
          payload: FETCH_STATES.FETHCED,
        });
        loginCallback();
      })
  };



发布评论

评论列表(0)

  1. 暂无评论