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

React Native form resets to initial values #3951

Closed
Salman9000 opened this issue Feb 3, 2024 · 2 comments
Closed

React Native form resets to initial values #3951

Salman9000 opened this issue Feb 3, 2024 · 2 comments

Comments

@Salman9000
Copy link

Form values should stay the same when executing onsubmit

Form values are being reset to empty values

import {
  Box,
  Button,
  Image,
  Input,
  Text,
  useTheme,
  // ScrollView,
  Flex
} from "native-base"
import { Formik } from "formik"
import { Ionicons } from "@expo/vector-icons"
import { useEffect, useRef, useState } from "react"
import { navigate } from "../../../rootNavigation"
import { setLoginClickedTrue } from "../../../store/loginClickedSlice"
import { useDispatch, useSelector } from "react-redux"

import { useSendVerificationEmail, useSignInEmailPassword } from "@nhost/react"
import AppVersion, { VERSION } from "../../components/AppVersion"
import LoaderModal from "../../components/LoaderModal"
import {
  View,
  Keyboard,
  ScrollView,
  Dimensions,
  StatusBar,
  TouchableWithoutFeedback
} from "react-native"
import { LinearGradient } from "expo-linear-gradient"
import { gql, useMutation } from "@apollo/client"
import AsyncStorage from "@react-native-async-storage/async-storage"
import { setSport } from "../../../store/sportSlice"
import { axiom, device } from "../../../config/util"
import { buttonColor } from "../../components/Colors"
import { TouchableOpacity } from "react-native"
import { nhost } from "../../../nhostClient"

const LoginScreen = ({ route, navigation }) => {
  const dispatch = useDispatch()
  const [loadingResetPassword, setLoadingResetPassword] = useState(false)
  const loginClicked = useSelector((state) => {
    return state.loginClicked.clicked
  })
  const { sendEmail, isLoading: loadingSendEmail } = useSendVerificationEmail()
  const {
    signInEmailPassword,
    isLoading: signInLoadng,
    needsEmailVerification,
    isError,
    error,
    isSuccess
  } = useSignInEmailPassword()
  const [togglePassword, setTogglePassword] = useState(true)
  const [signInloading, setSignInLoading] = useState(false)


  const signIn = async ({ email, password }) => {
    setSignInLoading(true)
    try {
      const res = await signInEmailPassword(
        //use nhost function to sign in
        email.toLowerCase().trim(),
        password.trim()
      )
      console.log({ res })
      if (res?.isError || !res.isSuccess) {
        //if there is error during sign in
        console.log("error in login")
        axiom.ingest("user-auth", [
          {
            version: VERSION,
            userEmail: email,
            action: "login",
            device,
            status: res?.error?.status ?? 500,
            error: res?.error ?? "Needs Email Verification"
          }
        ])
        console.log("sent axiom")
        setSignInLoading(false)
      } else {
        axiom.ingest("user-auth", [
          {
            version: VERSION,
            userEmail: email,
            action: "login",
            device,
            status: 200
          }
        ])
        navigation.navigate("DashboardDrawer")
        // getData()
      }
      setSignInLoading(false)
      return res
    } catch (e) {
      //some error in whole process
      console.log(JSON.stringify(e), "error")
    }
  }

  const handleSendVerificationEmail = async (email) => {
    console.log("click here")
    if (email) {
      try {
        const res = await sendEmail(email, {
          redirectTo: "https://tournapro.vercel.app/"
        })
        if (res?.isError) {
          axiom.ingest("logs", [
            {
              version: VERSION,
              userEmail: email,
              action: "resend verification email",
              device,
              error: res?.error,
              status: res?.error?.status ?? 500
            }
          ])
        } else {
          axiom.ingest("logs", [
            {
              version: VERSION,
              userEmail: email,
              action: "resend verification email",
              device,
              status: 200
            }
          ])
          alert(
            "Email sent successfully! Check spam folder if you cannot see the email."
          )
        }
      } catch (error) {
        axiom.ingest("logs", [
          {
            version: VERSION,
            userEmail: email,
            action: "resend verification email",
            device,
            error: error,
            status: error?.status ?? 500
          }
        ])
      }
    } else {
      alert("Enter Email Address")
    }
  }

  const handleSendResetPassword = async (email) => {
    setLoadingResetPassword(true)
    console.log("click here")
    console.log(email)
    if (email) {
      try {
        const res = await nhost.auth.resetPassword({
          email,
          options: {
            redirectTo:
              "https://tournapro.vercel.app/passwordReset"
          }
        })
        console.log(res)
        if (res?.error) {
          alert(res.error.message)
          axiom.ingest("logs", [
            {
              version: VERSION,
              userEmail: email,
              action: "Reset password",
              device,
              error: res?.error?.message,
              status: res?.error?.status ?? 500
            }
          ])
        } else {
          axiom.ingest("logs", [
            {
              version: VERSION,
              userEmail: email,
              action: "Reset password",
              device,
              status: 200
            }
          ])
          alert(
            "Password reset request sent to your email successfully. Check spam folder if you cannot see the email"
          )
        }
      } catch (error) {
        axiom.ingest("logs", [
          {
            version: VERSION,
            userEmail: email,
            action: "resend verification email",
            device,
            error: error,
            status: error?.status ?? 500
          }
        ])
      }
    } else {
      alert("Enter Email Address")
    }
    setLoadingResetPassword(false)
  }
  const { colors } = useTheme()

  const [screenHeight, setScreenHeight] = useState(
    Dimensions.get("window").height
  )
  const isFirstRef = useRef(false)
  const getScreenSize = () => {
    const statusBarHeight = StatusBar.currentHeight || 0
    const ScreenHeight = Dimensions.get("window").height
    setScreenHeight(ScreenHeight + statusBarHeight)
  }

  route.params ?? (isFirstRef.current = true)

  return (
    <TouchableWithoutFeedback
      height={screenHeight}
      onPress={() => Keyboard.dismiss()}
    >
      <Box height={screenHeight}>
        <Box bg={"white"} minW="full" flex={1} safeArea>
          <Box
            bg={"white"}
            w="full"
            justifyContent="center"
            alignItems="center"
            pt={2}
          >
            <Image
              alt="Tournapro logo"
              style={{ width: "100%", height: 180 }}
              resizeMode="contain"
              source={require("../../../assets/Login/TournaProLogo.png")}
            />
          </Box>
          <Box bg="white" flex={1} p={8} pt={1}>
            <Text fontSize={"22"} fontWeight={"500"} mb={0}>
              Login Details
            </Text>
            <Formik
              initialValues={{
                email: "",
                password: ""
              }}
              // enableReinitialize
              onSubmit={async (values) => {
                await signIn(values)
                console.log("here")
              }}
            >
              {({
                handleChange,
                handleBlur,
                handleSubmit,
                values,
                errors,
                touched
              }) => (
                <Box>
                  <Input
                    onChangeText={handleChange("email")}
                    onBlur={handleBlur("email")}
                    value={values.email}
                    variant="outline"
                    placeholder="Email"
                    autoComplete="email"
                    fontSize="sm"
                    color="black"
                    borderColor={"gray.300"}
                    borderRadius={"md"}
                    keyboardType="email-address"
                    selectionColor={colors.primary[600]}
                    _focus={{
                      borderColor: "gray.600",
                      bgColor: "white"
                    }}
                    autoCapitalize="none"
                    py={3}
                    mt={4}
                    mb={1}
                  />
                  {errors.email && touched.email && (
                    <Text color="red.500">{errors.email}</Text>
                  )}
                  <Input
                    onChangeText={handleChange("password")}
                    onBlur={handleBlur("password")}
                    value={values.password}
                    variant="outline"
                    placeholder="Password"
                    autoComplete="password"
                    fontSize="sm"
                    color="black"
                    borderColor={"gray.300"}
                    borderRadius={"md"}
                    selectionColor={colors.primary[600]}
                    type={togglePassword ? "password" : "text"}
                    _focus={{
                      borderColor: "gray.600",
                      bgColor: "white"
                    }}
                    autoCapitalize="none"
                    py={3}
                    mt={4}
                    mb={1}
                    InputRightElement={
                      <Box pr="3">
                        <Ionicons
                          onPress={() => setTogglePassword(!togglePassword)}
                          name={
                            togglePassword ? "eye-off-outline" : "eye-outline"
                          }
                          size={18}
                          color={colors.black}
                        />
                      </Box>
                    }
                  />
                  {errors.password && touched.password && (
                    <Text color="red.500">{errors.password}</Text>
                  )}

                  <Box mt={2} ml="auto">
                    <Text
                      textAlign="center"
                      bold
                      color={colors.primary[900]}
                      onPress={async () => {
                        if (!values.email) {
                          alert("Please enter your email")
                        } else {
                          console.log("meow")
                          handleSendResetPassword(values.email)
                        }
                      }}
                    >
                      Forgot Password?
                    </Text>
                  </Box>

                  <TouchableOpacity
                    onPress={() => {
                      dispatch(setLoginClickedTrue())
                      setSignInLoading(true)
                      handleSubmit()
                      Keyboard.dismiss()
                    }}
                    activeOpacity={0.8}
                    style={{
                      elevation: 2,
                      marginVertical: 6,
                      alignSelf: "center",
                      height: 53,
                      width: "100%",
                      backgroundColor: buttonColor,
                      borderRadius: 4,
                      display: "flex",
                      alignContent: "center",
                      justifyContent: "center"
                    }}
                  >
                    <Text
                      textAlign={"center"}
                      fontWeight={700}
                      fontSize={17}
                      color={"white"}
                    >
                      Login
                    </Text>
                  </TouchableOpacity>
                  {/* <Button
                    alignSelf={"center"}
                    size="lg"
                    borderRadius={4}
                    width={281}
                    height={53}
                    onPress={() => {
                      dispatch(setLoginClickedTrue())
                      setSignInLoading(true)
                      handleSubmit()
                      Keyboard.dismiss()
                    }}
                    // bgColor={"#284E8A"}
                    colorScheme={"blue"}
                    my={4}
                  >
                    <Text
                      textAlign={"center"}
                      fontWeight={700}
                      fontSize={21}
                      color={"white"}
                    >
                      Login
                    </Text>
                  </Button> */}

                  <Flex
                    direction="row"
                    justifyContent="space-around"
                    alignItems="center"
                  >
                    {/* First linear gradient */}
                    <LinearGradient
                      colors={["white", buttonColor]}
                      start={{ x: 0, y: 0 }}
                      end={{ x: 1, y: 0 }}
                      style={{ width: 90.62, height: 2.65 }}
                    />
                    <Text
                      textAlign="center"
                      underline
                      bold
                      color={colors.primary[900]}
                      onPress={() => navigate("SignUpScreen")}
                    >
                      Or Sign up
                    </Text>
                    {/* Second linear gradient */}
                    <LinearGradient
                      colors={[buttonColor, "white"]}
                      start={{ x: 0, y: 0 }}
                      end={{ x: 1, y: 0 }}
                      style={{ width: 90.62, height: 2.65 }}
                      useAngle={true}
                      angle={180}
                    />
                  </Flex>
                  {needsEmailVerification &&
                    loginClicked &&
                    !isSuccess &&
                    isFirstRef.current && (
                      <Box my={4}>
                        <Text color="red.600" bold textAlign={"center"}>
                          Verify your email address and login.
                        </Text>
                        <Text color="red.600" bold textAlign={"center"}>
                          Open your email to verify your email
                        </Text>
                        <Text color="red.600" bold textAlign={"center"}>
                          Didn't recieve verification?{" "}
                          <Text
                            onPress={() =>
                              handleSendVerificationEmail(values.email)
                            }
                            underline
                          >
                            Click here
                          </Text>{" "}
                          to send verification link again
                        </Text>
                      </Box>
                    )}
                  {needsEmailVerification &&
                    !isFirstRef.current &&
                    !isSuccess && (
                      <Box my={4}>
                        <Text color="red.600" bold textAlign={"center"}>
                          Verify your email address and login
                        </Text>
                        <Text color="red.600" bold textAlign={"center"}>
                          Open your email to verify your email
                        </Text>
                        <Text color="red.600" bold textAlign={"center"}>
                          Didnt recieve verification?{" "}
                          <Text
                            onPress={() =>
                              handleSendVerificationEmail(values.email)
                            }
                            underline
                          >
                            Click here
                          </Text>{" "}
                          to send verification link again
                        </Text>
                      </Box>
                    )}

                  {isError && (
                    <Box my={4}>
                      <Text color="red.600" bold textAlign={"center"}>
                        {error?.message}
                      </Text>
                    </Box>
                  )}
                </Box>
              )}
            </Formik>
          </Box>
        </Box>
        <AppVersion />
        <Image
          width={"100%"}
          alt="background"
          position={"absolute"}
          bottom={0}
          source={require("../../../assets/Login/Vector.png")}
        />
        <LoaderModal
          isLoading={
            signInloading ||
            loadingSendEmail ||
            signInLoadng ||
            loadingResetPassword
          }
        />
      </Box>
    </TouchableWithoutFeedback>
  )
}

export default LoginScreen
Software Version(s)
Formik 2.4.5
React 18.2.0
React native 0.71.8
npm/Yarn yarn
Operating System android/ios
@erashu212
Copy link

@Salman9000 Can you create a code sandbox using https://expo.dev/

@Salman9000
Copy link
Author

@Salman9000 Can you create a code sandbox using https://expo.dev/

It seems the error isnt related to Formik, but rather the nhost sdk I am using. The nhost hooks are not compatible with react native as of yet which is causing bugs like these. I am closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants