Cimo
Cimo

Reputation: 185

How to pass state from component to file app.js in React

I have to pass my state from Authentication.js to App.js, to make certain functionalities available to registered users.

This is my file Authentication.js

import { useState } from "react"
import MyButton from "../componens/myButton"
import styles from "../style/authentication.module.css"
import Spinner from "../componens/Spinner"
import axios from "axios"

const Authentication = () =>{

const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [loading, setLoading] = useState(false)
const [registration, setRegistration] = useState(true)
const [state, setState] = useState(null)

let MyRegistration = null;

const handleSubmit = async (e) =>{
    e.preventDefault()
    setLoading(true)
    try {
        const userKey = `AIzaSyCYe1XVuJVflRie0sf1y01RNrmQ77Dmp4Q`
        let urlAPI = `https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${userKey}`
        if (!registration) {
            urlAPI = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${userKey}`
        }
        setEmail(email);
        setPassword(password);
        MyRegistration = await axios.post(urlAPI,{
            email : email,
            password : password,
            returnSecureToken : true
        })
        setState(MyRegistration)
        setLoading(false);

        return MyRegistration

    } catch (error) {
        setLoading(false)
        console.log(error)
    }
}
    return <div className={styles.formContainer}>
        <h1>Authentication</h1>
        <form onSubmit={handleSubmit} action="">
            <p>Email</p>
            <input placeholder="Your email" type="email" value={email} onChange={handleEmail} />
            <p>Password</p>
            <input placeholder="Your Password" type="password" value={password} onChange={handlePassword} />
            {loading ? <Spinner/> :
            <MyButton  title={registration ? 'sign up' : 'Sign in'} handleClickButton={handleSubmit} />}
            <MyButton title={registration ? 'Go to Sign in' : 'Go to sign up'} handleClickButton={changeMode}/>
        </form>
    </div>
}
export default Authentication;

This is my file App.js

import Home from './pages/Home';
import Book from './pages/Book'
import {Route, Switch} from 'react-router-dom'; 
import SavedBooks from './pages/SavedBooks';
import Header from './componens/Header';
import BookChapter from './pages/BookChapter';
import Authentication from './pages/Authentication';
import {useState} from "react";

function App(props) {

const [userData,  setUserData] = useState("");

  return (
    <div>
      <Header/>
      <Switch>
        <Route exact path="/" render={(props) => <Home userData={userData}/>}/>
        <Route exact path="/book/:id" component={Book}/>
        <Route exact path="/savedbooks" component={SavedBooks}/>
        <Route exact path="/book/:id/chapter/:numero" component={BookChapter}/>
        <Route exact path="/authentication" render={(props) => <Authentication setUserData={setUserData(this.state)}/> }/>
      </Switch>
    </div>
  )
}
export default App;

But the response is: TypeError: Cannot read properties of undefined (reading 'state')

Upvotes: 1

Views: 1248

Answers (1)

Tarun
Tarun

Reputation: 104

You cannot pass the state declared in Authentication.js to its parent App.js . So, you need to make a useState in App.js and pass the state and its corresponding setterFunction onto the child i.e Authentication.js. This is known as lifting up the state.

Move const [state, setState] = useState(null) to App.js and use the state variable in App.js and pass it onto child like this

<Route exact path="/authentication" render={(props) => <Authentication state={state} setState={setState}/> }/>

Upvotes: 2

Related Questions