Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds user authentication workflow #3

Merged
merged 1 commit into from
Jun 5, 2023
Merged

Conversation

swapnilkamat23
Copy link
Collaborator

@swapnilkamat23 swapnilkamat23 commented May 19, 2023

This PR -

  1. Implements login api that makes a service call to authenticate the user
  2. Implements helper functions to store key values to the async store
  3. Stores the login object in the async store after successful authentication (TO BE CHANGED - Currently the login object is user object. As discussed, we will separate the user object from login object. Login object should only contain the authentication status, true if success and false if failed to auth.)
  4. Implements an account screen which houses a logout button to complete/test the auth workflow. (NOTE - the account screen is NOT a focus of this PR. The CRUD operations in account screen will be added in upcoming PR)
  5. Implements a reusable component TextInput that we can use across the app
  6. Implements ActivityIndicator, which is basically a loading indicator when waiting for synchronous/blocking api calls (such as login)
  7. Implements an animated SplashScreen, visible during app load
Simulator.Screen.Recording.-.iPhone.12.Pro.Max.-.2023-05-18.at.22.02.01.mp4

Coming up in next PR -

  1. Add a component for error messages so that when the user authentication fails it displays the error message.
  2. Connect the account screen to the service for CRUD operations

const authContext = useContext(AuthContext);
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [username, setUsername] = useState();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ndedhia1210 Updated this line per your comment on the previous PR.

App.js Outdated
import { NavigationContainer } from "@react-navigation/native";
import * as SplashScreen from "expo-splash-screen";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I liked this.

App.js Outdated
Comment on lines 29 to 34
} finally {
setIsReady(true);
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need Finally? Because incase of error we should display error screen and having boolean for ready will not distinguish whether it is succeeded or failed?

How about we initialize loadingState which can have values like [Succeeded, Failed, Loading, Idle]
So basically

// Some other file 
export enum AsyncStatus {
  Idle = 'Idle',
  Loading = 'Loading',
  Succeeded = 'Succeeded',
  Failed = 'Failed',
}


// This file
const [appStatus, setAppStatus] = useState(Async.Idle);
....
try {
  ...
 setAppStatus(Async.Succeeded)
} catch(error) {
 setAppStatus(Async.Failed)
}
...
// Just demonstrating what we should render
switch(appStatus) {
 case Async.Idle: return null;
 case Async.Failed: return <ErrorComponent />;
 case Async.Succeeded: return <ActualComponent />;
 case Async.Loading: return <SplashScreen />;
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loved this idea.. Updated

import { create } from "apisauce";

const apiClient = create({
baseURL: "https://ill-gold-parrot-sock.cyclic.app",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to place endpoints and other details in environment (.env) file or Config.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of refactoring this later, but why not now!?!.. updated :)

Comment on lines 4 to 6
const [data, setData] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 3 state can be combined to one say status and we can reuse the AsyncStatus logic here. which I described above.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

Comment on lines +3 to +5
const login = (username, password) =>
client.post("/login", { username, password });

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking comment

It is okay for now but we should also add validation logic before service call.
For eg: validate username and password are not null, regex (if any) etc...

-> This will help to prevent service call for which backend will throw error.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, will create a separate dedicated PR for validation.


import AsyncStorage from "@react-native-async-storage/async-storage";

const storeData = async (key, value) => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is interesting and liked it, would like to understand the running scenarios.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, lets discuss scenarios during our next sync-up

@@ -11,7 +18,10 @@ import { SafeAreaView, StyleSheet, View } from "react-native";
function Screen({ children, style }) {
return (
<SafeAreaView style={[styles.screen, style]}>
<View style={style}>{children}</View>
<StatusBar barStyle={"dark-content"} />
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

function authenticate() {
authContext.setUser({});
}
const keyboardVerticalOffset = Platform.OS === "ios" ? 20 : 0;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for thinking about this behavior.

@swapnilkamat23 swapnilkamat23 force-pushed the swap/user-auth branch 3 times, most recently from b56f381 to 28cc16d Compare June 3, 2023 21:29
App.js Outdated
function renderSwitch() {
switch (appStatus) {
case AsyncStatus.Succeeded:
return <>{user ? <AppNavigator /> : <AuthNavigator />}</>;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<></> i not required can be skipped.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated


const request = async (...args) => {
setApiStatus(AsyncStatus.Loading);
const response = await apiFunc(...args);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s use promises for this.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is okay to address in next pr

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will update that in next PR

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried implementing the promise here just now but was facing some errors and the code started looking a little ugly. I would suggest we use async-await along with try-catch to handle all scenarios. With async-await, the code looks more maintainable and organized as compared to promise. I would like to hear your concerns about async-await. Let's discuss this during our sync up.

};

const getCurrentSettings = () => {
if (__DEV__) return settings.dev;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where will we store this DEV does it mean from environment variable? Or from webpack?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEV is a global variable from react native packager. It is set during runtime by react native and is available to use anywhere in the app for encapsulating environment specific code blocks.

@swapnilkamat23 swapnilkamat23 merged commit 0014b18 into main Jun 5, 2023
@swapnilkamat23 swapnilkamat23 added the new feature New feature addition label Oct 16, 2023
@swapnilkamat23 swapnilkamat23 self-assigned this Oct 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature New feature addition
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants