0
votes

I'm creating a login and signup interface with Firebase, in my Ionic(React) app project, below are the snippet of my code.

interface LoginProps extends RouteComponentProps<any> {}
interface AuthProps {}

const Login: FC<LoginProps> = ({ history }) => {
  const handleLogin = useCallback(
    async event => {
      event.preventDefault();
      const { email, password } = event.target.elements;
      try {
        await Firebase
          .auth()
          .signInWithEmailAndPassword(email.value, password.value);
        history.push("/dashboard");
      } catch (error) {
        alert(error);
      }
    },
    [history]
  );

  const { currentUser } = useContext<AuthProps>(AuthContext);

  if (currentUser) {
    return <Redirect to="/" />;
  }

I got this error messages:

[react-scripts] TypeScript error in /Users/matheuslira/Desktop/brasilsul-repasse/src/pages/Login.tsx(43,49):

[react-scripts] Argument of type '{ AuthContext: React.Context; AuthProvider: ({ children }: { children: any; }) => JSX.Element; }' is not assignable to parameter of type 'Context'.

[react-scripts] Type '{ AuthContext: Context; AuthProvider: ({ children }: { children: any; }) => Element; }' is missing the following properties from type 'Context': Provider, Consumer TS2345

the error message point to this part of the code:

const { currentUser } = useContext(AuthContext);

I don't know how to fix this error.

// Edit

AuthContext Code

import React, { useEffect, useState, createContext } from "react"
import Firebase from "./firebase"

export const AuthContext = createContext(null)
export const AuthProvider = ({ children }) => {
    const [currentUser, setCurrentUser] = useState(null)

    useEffect(() => {
        Firebase.auth().onAuthStateChanged(setCurrentUser)
    }, [])

    return (<AuthContext.Provider value = {{currentUser}} >{children}</AuthContext.Provider>)
}

export default {
    AuthContext,
    AuthProvider
}
1
AuthProps is supposed to be??... where is AuthContext, I think providing the code from your AuthContext would be helpfulAaron Saunders
I added the AuthContext CodeMatheus Lira
is the context file have extension .tsxAaron Saunders
Yes, all of my files have .tsx extensionMatheus Lira

1 Answers

1
votes

This is my solution and it seems to be working fine

// context-fb.tsx
import React, { useEffect, useState, createContext } from "react";
import Firebase, { User } from "firebase";

export interface IAuthContext {
  user: User;
}

const AuthContext = createContext<IAuthContext | null>(null);
const AuthProvider: React.FC = ({ children }) => {
  const [currentUser, setCurrentUser] = useState<IAuthContext | null>(null);

  useEffect(() => {
    Firebase.auth().onAuthStateChanged((user: any) => {
      console.log('state set', user)
      setCurrentUser({ user });
    });
  }, []);

  return (
    <AuthContext.Provider value={currentUser}>{children}</AuthContext.Provider>
  );
};

export default {
  AuthContext,
  AuthProvider
};

the basic parts of Login.tsx

import React, { FC, useCallback, useContext } from "react";
import { RouteComponentProps, Redirect } from "react-router";

import Firebase from "firebase";

import Stuff, { IAuthContext } from "../context-fb";

interface LoginProps extends RouteComponentProps<any> {}

const Login: FC<LoginProps> = ({ history }) => {
  const handleLogin = useCallback(
    async event => {
      event.preventDefault();
      const { email, password } = event.target.elements;
      try {
        await Firebase.auth().signInWithEmailAndPassword(
          email.value,
          password.value
        );
        history.push("/dashboard");
      } catch (error) {
        alert(error);
      }
    },
    [history]
  );

  const authInfo = useContext<IAuthContext|null>(Stuff.AuthContext);
  console.log("rendered login", authInfo?.user )

  return authInfo?.user ?  <Redirect to="/home" /> : <div></div>;
};

export default  Login

and then my App.tsx

import Stuff from "./context-fb";

const App: React.FC = () => {

  return <IonApp>
    <IonReactRouter>
      <Stuff.AuthProvider>
        <IonRouterOutlet>
          <Route path="/home" component={Home} exact={true} />
          <Route path="/login" component={Login} exact={true} />
          <Route exact path="/" render={() => <Redirect to="/login" />} />
        </IonRouterOutlet>
      </Stuff.AuthProvider>
    </IonReactRouter>
  </IonApp>
};

export default App;