Search code examples
reactjsgatsbyreact-props

Pass props with React and Gatsby


I have all of my firebase functions and variables inside of my Login.js but my Dashboard.js needs to have access to two of those props aswell. For some reason no matter what I try I cannot get it to work. Because I am using gatsby these are two different pages and as well.

This is my Login.js code (where all my functions that I want to pass are)

import React, { useState, useEffect, Component } from "react";
import "../css/Login.css";
import { Link, navigate } from "gatsby";
import BackGround from "../components/bg";
import Navbar from "../components/navbar";
import fire from "../components/fire";

const Login = () => {
  const [user, setUser] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [emailError, setEmailError] = useState("");
  const [passwordError, setPasswordError] = useState("");
  const [hasAccount, setHasAccount] = useState(false);

  const clearInputs = () => {
    setEmail("");
    setPassword("");
  };

  const clearErrors = () => {
    setEmailError("");
    setPasswordError("");
  };

  const handleLogin = () => {
    clearErrors();
    fire
      .auth()
      .signInWithEmailAndPassword(email, password)
      .catch((err) => {
        switch (err.code) {
          case "auth/invalid-email":
          case "auth/user-disabled":
          case "auth/user-not-found":
            setEmailError(err.message);
            break;
          case "auth/wrong-password":
            setPasswordError(err.message);
            break;
        }
      });
  };

  const handleSignup = () => {
    clearErrors();
    fire
      .auth()
      .createUserWithEmailAndPassword(email, password)
      .catch((err) => {
        switch (err.code) {
          case "auth/email-already-in-use":
          case "auth/invalid-email":
            setEmailError(err.message);
            break;
          case "auth/weak-password":
            setPasswordError(err.message);
            break;
        }
      });
  };

  const handleLogout = () => {
    fire.auth().signOut();
  };

  const authListener = () => {
    fire.auth().onAuthStateChanged((user) => {
      if (user) {
        clearInputs();
        setUser(user);
      } else {
        setUser("");
      }
    });
  };

  useEffect(() => {
    authListener();
  }, []);

  return (
    <div>
      <BackGround />
      <Navbar />
      {/* {user
        ? (navigate("/dashboard", { replace: true }),
          (<Dashboard handleLogout={handleLogout} user={user} />))
        : null} */}
      {user ? <h1>User</h1> : <h1>No user</h1>}
      <section className="form-signin">
        {hasAccount ? (
          <h2 className="form-signin-heading">Login</h2>
        ) : (
          <h2 className="form-signin-heading">Signup</h2>
        )}
        <label className="control-label form-labels">Email</label>
        <input
          className="form-input"
          placeholder="Enter email"
          type="text"
          autoFocus
          required
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <p className="errorMsg">{emailError}</p>
        <label className="control-label form-labels">Password</label>
        <input
          className="form-input"
          placeholder="Enter password"
          type="password"
          required
          value={password}
          onChange={(e) => setPassword(e.target.value)}
        />
        <p className="errorMsg">{passwordError}</p>

        {hasAccount ? (
          <>
            <p className="AHAC">
              Not Registered?{" "}
              <span onClick={() => setHasAccount(!hasAccount)} className="AHAC">
                Create an account.
              </span>
            </p>
            <center>
              <button className="form-button" onClick={handleLogin}>
                Login
              </button>
            </center>
          </>
        ) : (
          <>
            <p className="AHAC">
              Already have an account?{" "}
              <span className="AHAC" onClick={() => setHasAccount(!hasAccount)}>
                Sign In.
              </span>
            </p>
            <center>
              <button className="form-button" onClick={handleSignup}>
                Signup
              </button>
            </center>
          </>
        )}
      </section>
    </div>
  );
};

export default Login;

This is my Dashboard.js (need access to handleLogout function and user variable)

import { navigate } from "gatsby";
import React from "react";
import BackGround from "../components/bg";
import Navbar from "../components/navbar";
const Dashboard = ({ handleLogout, user }) => {
  return (
    <div>
      <BackGround />
      <Navbar />
      {/* {user ? null : navigate("/Login")} */}
      {user ? <h1>User</h1> : <h1>No user</h1>}

      <h1 className="welcome-text">Welcome, User</h1>
      <h1 className="page-header">You have generated 100 Facts!</h1>
      <center>
        <button className="logout-button" onClick={handleLogout}>
          Logout
        </button>
      </center>
    </div>
  );
};

export default Dashboard;

As always any help would be greatly appreciated thank you!


Solution

  • You can achieve this using a combination of React Hooks and React Context. Yes, you can use React Context with Gatsby. Take a look at this useAuth. You could use this as a foundation to build your own custom hook. Something like this:

    Create your custom hook

    const AuthContext = React.createContext();
    
    export function AuthProvider({ children }) {
      const auth = useProvideAuth();
      return <AuthContext.Provider value={auth}>{children}</AuthContext.Provider>;
    }
    
    export const useAuth = () => {
      return useContext(authContext);
    };
    
    function useProvideAuth() {
      //The auth state and methods you need
      const [user, setUser] = React.useState("");
      const [email, setEmail] = React.useState("");
      const [password, setPassword] = React.useState("");
      const [emailError, setEmailError] = React.useState("");
      const [passwordError, setPasswordError] = React.useState("");
      const [hasAccount, setHasAccount] = React.useState(false);
    
      const clearInputs = () => {
        //...
      };
    
      const clearErrors = () => {
        //...
      };
    
      const handleLogin = () => {
        //...
      };
    
      const handleSignup = () => {
        //...
      };
    
      const handleLogout = () => {
        //...
      };
    
      const authListener = () => {
        //...
      };
    
      React.useEffect(() => {
        //...
      }, []);
    
      return {
        user,
        handleLogin,
        handleLogout,
      };
    }
    

    Add the provider in the Gatsby Browser file (gatsby-browser.js)

    import React from "react"
    import { AuthProvider } from "./src/context/AuthContext"
    export const wrapRootElement = ({ element }) => (
      <AuthProvider>{element}</AuthProvider>
    )
    

    Use it in your components

    const Dashboard = ({ handleLogout, user }) => {
      const auth = useAuth();
      // you can access auth.user, auth.logout
      return (
        <div>...</div>
      );
    };