2

I have the following code which check the user_id if available and then log me in but it logs me in only if I refresh the app. Any idea how to make this happen without this?

This is the order of functions:

First when you click the login button from Login.js:

<TouchableOpacity onPress={handleSubmit(_signIn)} style={{margin: 10, alignItems: 'center'}}>

then _signIn function which is in Login.js

_signIn = (values, dispatch) => {
  const email = values.email;
  const password = values.password;
  dispatch(loginUser(email, password));
}

Now we dispatched email and password to loginUser from authActions.js

export function loginUser(email, password) {
  return function (dispatch) {
    return axios.post(SIGNIN_URL, { email, password }).then((response) => {
      var { user_id, token } = response.data;
      onSignIn(user_id); // Here I pass 'user_id' to onSignIn function
    }).catch((error) => {
      dispatch(addAlert("Could not log in."));
    });
  };
}

Now we get the user_id from loginUser inside Auth.js

import { AsyncStorage } from "react-native";

const USER_KEY = "auth_key";

export const onSignIn = (user_id) => AsyncStorage.setItem(USER_KEY, user_id);
export const onSignOut = () => AsyncStorage.removeItem(USER_KEY);

export const isSignedIn = () => {
  return new Promise((resolve, reject) => {
    AsyncStorage.getItem(USER_KEY)
      .then(res => {
        if (res !== null) {
          resolve(true);
        } else {
          resolve(false);
        }
      })
      .catch(err => reject(err));
  });
};

Now in App.js I am calling the function isSignedIn to check if user_id is available and if so will choose which screen to show

 constructor(props) {
    super(props);

    this.state = {
      signedIn: false,
      checkedSignIn: false
    };
  }

  componentDidMount() {
    isSignedIn()
      .then(res => this.setState({ signedIn: res, checkedSignIn: true }))
      .catch(err => alert("An error occurred"));
  }

  render() {
    const { checkedSignIn, signedIn } = this.state;

    // If we haven't checked AsyncStorage yet, don't render anything (better ways to do this)
    if (!checkedSignIn) {
      return null;
    }

    const Layout = createRootNavigator(signedIn);
Markus Hayner
  • 2,601
  • 1
  • 22
  • 50

1 Answers1

0

It`s not async function callback issue - I do know how to use it, coz you are already use it in the isSignedIn function.

You did called onSignIn(userId), but you inform nobody about it. Those function, that calls isSignedIn should somehow know about a user logged in.

Based on this issue and previous one, I guess you should choose an architecture of your app (redux or just functional programming or something else) and keep it in mind.
If you wanna use redux, you should dispatch an action about a user logged in and reflect to state change where you need it.

Kirill Glazunov
  • 480
  • 2
  • 10
  • 2
    Agreed. Looks like the problem is that you check `isSignedIn()` when the app mounts - that is, before the user signs in - and don't check it again. State management solution would help here, so that App can be notified when the user gets logged in. – Kos Apr 24 '18 at 15:52
  • @Kos I've checked the order of functions and you are right. Now my question is how do I call `isSignedIn()` from mount after I am passing the `user_id` inside `Auth.js`? – Markus Hayner Apr 24 '18 at 17:30
  • @MarkusHayner it\`s not about an order of functions - it\`s about state management. There is how redux work - it is a state, that get changes by actions and has a subscriptions to the changes. See `react-redux->connect->mapStateToProps` to clarify how to get renewed value to a component from the state. – Kirill Glazunov Apr 25 '18 at 05:24