2

I just switched my app's data flow to Redux and I am not really getting it.

My wise component looks like:

const LoginPage = ({ auth, doLogin, doLogout }) => (

    <div>

      <NavBar/>
        <div className="row">
            <div style={{display: 'flex', justifyContent: 'center'}} className="col-md-4 col-md-offset-4">
                <LoginForm doLogin={doLogin} doLogout={doLogout} auth={auth} />
            </div>
        </div>
      </div>

);
const mapStateToProps = state => ({
  auth: state.auth,
});

export default connect(mapStateToProps, { doLogin, doLogout })(LoginPage);

So, from what I understood, I have to mapStateToProps to call the states from the store to map into the props of the component.

Now, on my LoginForm component, which is the component that has the field for login inputs, I pass in doLogin doLogout and auth.

What I am not sure of is, where to use the API call that POSTs the login information.

In my auth.js, I wrote my doLogin as:

export const doLogin = (username, password) => {
    //console.log(username, password);
    //return {
    //    type: 'types.AUTH_LOGIN'
    //};
    var self = this;

    axios.post('http://localhost:5000/signin', 
    {
        username: username, 
        password: password
    })
        .then(function (response) {

            console.log(response);
            if(response.data.status === "Successful"){
                console.log("Login successfull");
            }

            else{
                console.log("There is no user with the given username and password");
                //alert("Username does not exist");
            }
        }
    )
    .catch(function (error) {

    console.log(error);
    });
};

As you see on my comment,

//return {
//    type: 'types.AUTH_LOGIN'
//};

I tried to return an object to the action creator. But I am not sure how this works and how my state in the store changes.

I know reducers returns the newly changed state, but how do we make the change?

To summarize, my goal is to change the state isLoggedin to true based upon my axios call used in the action.

Dawn17
  • 7,825
  • 16
  • 57
  • 118
  • to dispatch async action, use some middleware like this: `redux-thunk`, read this answer you will get all the answers and solution also [**why we need middleware and use of redux-thunk**](https://stackoverflow.com/questions/34570758/why-do-we-need-middleware-for-async-flow-in-redux) – Mayank Shukla Jun 25 '18 at 05:06
  • Thanks. But the comment does not really answer how states change based on the API call in Redux. – Dawn17 Jun 25 '18 at 05:11
  • have you checked the answers of linked ques? – Mayank Shukla Jun 25 '18 at 05:30

1 Answers1

2

First congrats for stating with redux :) it's hard at the start, but super awesome later.

  • in your "mapDispatchToProps" you are supposed to have a function that returns an object of keyed functions.

ie:

const mapDispatchToProps = dispatch => {
    return ({
        login: (user, pass) => dispatch(loginActionCreator(user, pass)),
        logout: _ => dispatch(logoutActionCreator())
    })
}

after we have done that we need to handle our above action creators.

Before that some notes:

  • redux actions do NOT handle async calls
  • you will need to use some kind of middleware
  • redux-thunk is super nice and easier to understand
  • redux-saga is a bit more complexed but more powerful
  • I would start with redux-thunk, and add examples for our above situation

actionCreators.js

const loginActionCreator = (username, pass) => {
    return dispatch => {
        dispatch({type: 'login_start'});

        axios.post('http://localhost:5000/signin', {
            username: username, 
            password: password
        })
        .then(function (response) {

            console.log(response);
            if(response.data.status === "Successful"){
                console.log("Login successfull");
                dispatch({type: 'login_success', data: response.data})
            }
            else{
                console.log("There is no user with the given username and password");
                dispatch({type: 'login_failed', err: 'no username found'})
            }
        }

        .catch(function (error) {
            console.log(error);
            dispatch({type: 'login_failed', err: error'})
        });

    }
}

const logoutActionCreator = () => {
    return dispatch => {
        dispatch({type: 'logout'});
    }
}

The examples are far from perfect, but they are for a general idea. You will need to start digging on async actions inside redux like the libraries I mentioned above.

Enjoy!

Tzook Bar Noy
  • 11,337
  • 14
  • 51
  • 82
  • Thanks a lot. In your example, which is the part that I have to call the `axios` `POST` call? – Dawn17 Jun 25 '18 at 14:56
  • where I added the "loginAjaxCall" this is your axios or any other ajax library call. This example uses promises but you can use callbacks or whatever. Just make sure you understand the flow. "dispatch" only gets an object nothing more or nothing less – Tzook Bar Noy Jun 25 '18 at 15:15
  • If you look at my `axios` call in my question, I am not sure where the `dispatch` has to be and what effect it brings. When and why do we need `dispatch`? – Dawn17 Jun 25 '18 at 15:28