简体   繁体   中英

React Mulitple rendering functional component

hy i begin in react and i try to get user data from my api with my cookie, i have the data but when i console.log() the user data i have 4 undefined and then 2 same object data. The problem is i don't know why and when i try to get user.id in an other components using props i have tpyerror id undefined.

import React, {useState, useEffect} from "react";
import NavBar from "./component/NavBar";
import Navigation from "./component/Navigation"
import Cookie from "js-cookie"
import axios from "axios"
import "./App.css";

function App() {
  const [user, setUser] = useState()
  const [logged, setLogged] = useState(false)
  const cookie = Cookie.get("login")

  useEffect(() => {
     axios.post('/getdatafromcookie', cookie)
    .then((res) => {
        if(res.data.success === true){
            setLogged(true)
            setUser(res.data.user)
        }
    })
}, [])

console.log(user)
return (
    <div className="App">
        <header className="NavHeader">
            <NavBar user={user} logged={logged} />
        </header>
        <Navigation user={user} logged={logged}/>
    </div>
 );
}

export default App;

And the console log shows me:

  • Undefined
  • Undefined
  • Undefined
  • Undefined
  • {id: "31", email:"test@test.fr" etc.....}
  • {id: "31", email:"test@test.fr" etc.....}

Navbar

import React, { useState, useEffect } from "react";
import RegisterForm from "../component/RegisterForm";
import RegisterLogin from "../component/RegisterLogin";
import { Navbar, Nav, Dropdown } from "react-bootstrap";
import { Button } from "@material-ui/core"

export default function NavBar(props) {
    const [modalLoginShow, setModalLoginShow] = useState();
    const [modalRegisterShow, setModalRegisterShow] = useState();
    const user = props.user
    const islogged = props.logged
    

   if(islogged === false)
    {
        return (
            <Navbar collapseOnSelect expand="lg" bg="transparent" variant="light">
                <Navbar.Brand href="/">Matchandate</Navbar.Brand>
                <Navbar.Toggle aria-controls="responsive-navbar-nav" />
                <Navbar.Collapse id="responsive-navbar-nav">
                    <Nav className="mr-auto"></Nav>
                    <Nav>
                        <Nav.Link onClick={() => setModalLoginShow(true)}>
                            <Button variant="contained" color="secondary">Login</Button>
                        </Nav.Link>
                        <Nav.Link onClick={() => setModalRegisterShow(true)}>
                            <Button variant="contained" color="secondary" >Register</Button>
                        </Nav.Link>
                    </Nav>
                </Navbar.Collapse>
                <RegisterLogin show={modalLoginShow} onHide={() => setModalLoginShow(false)} />
                <RegisterForm show={modalRegisterShow} onHide={() => setModalRegisterShow(false)} />
            </Navbar>
        )
    }
    return(
        <Navbar collapseOnSelect expand="lg" bg="transparent" variant="light">
                <Navbar.Brand href="/">Matchandate</Navbar.Brand>
                <Navbar.Toggle aria-controls="responsive-navbar-nav" />
                <Navbar.Collapse id="responsive-navbar-nav">
                    <Nav className="mr-auto"></Nav>
                    <Nav>
                        <Nav.Link href="/profile">
                            <Button variant="contained" color="primary">Profile</Button>
                        </Nav.Link>
                        <Nav.Link href="/logout">
                            <Button variant="contained" color="primary" >Logout</Button>
                        </Nav.Link>
                    </Nav>
                </Navbar.Collapse>
            </Navbar>
    )
}

Navigation

import React from "react"
import Slider from "./SliderHome";
import Activate from "./Activate";
import ForgotPwd from "./Pages/ForgotPwd"
import ChangePwd from "./Pages/ChangePwd"
import UserProfile from "./Pages/UserProfil";
import ErrorPage from "./Pages/ErrorPage"
import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom";


export default function Navigation(props){
  const user = props.user
  const islogged = props.logged
  
  if(islogged){
    return(
      <Router>
      <Switch>
        <Route exact path="/" exact component={Slider} />
        <Route exact path="/profile" component={() => <UserProfile user={user} />} />
        {/* <Route path="/user/:id" component={ChangePwd}/> */}
        <Route path="/" component={ErrorPage} />
      </Switch>
  </Router>
    )
  }
  return (
    <Router>
      <Switch>
        <Route exact path="/" exact component={Slider} />
        <Route path="/activate"  component={Activate} />
        <Route path="/forgot-pwd" component={ForgotPwd}/>
        <Route path="/changepwd" component={ChangePwd}/>
        {/* <Route path="/user/:id" component={ChangePwd}/> */}
        <Route path="/" component={ErrorPage} />
      </Switch>
  </Router>
  )
}

This happens because useEffect is executed after the first render, so, the first time user is null, you will need to guard your code to render once you have data inside user

return user ? <div className=“app”><NavBar user={user}/></div> : <div>loading</div>)

The logs being printed so many times is because strict mode in development

In yours first render: your user is undefined it's normal because your are not defined a default value in your usestate you can change your code by this const [user, setUser] = useState({}) or this

import React, {useState, useEffect} from "react";
import NavBar from "./component/NavBar";
import Navigation from "./component/Navigation"
import Cookie from "js-cookie"
import axios from "axios"
import "./App.css";

function App() {
  const [user, setUser] = useState()
  const [logged, setLogged] = useState(false)
  const cookie = Cookie.get("login")

  useEffect(() => {
     axios.post('/getdatafromcookie', cookie)
    .then((res) => {
        if(res.data.success === true){
            setLogged(true)
            setUser(res.data.user)
        }
    })
}, [])

console.log(user)
return (
    <div className="App">
        <header className="NavHeader">
            {user ? <NavBar user={user} logged={logged} /> : "loading"}
        </header>
        {user ? <Navigation user={user} logged={logged}: "loading" />
    </div>
 );
}

export default App;

The problem is i don't know why and when i try to get user.id in an other components using props i have tpyerror id undefined.

The reason for that is that you try to get the id of the user before the user is loaded , which means you're doing something like null.id which is undefined (depends on what useState returns when called without any arguments, probably null)

The reason you get multiple Undefined in console.log is:

the first time your App component is rendered, useEffect didn't finish calling the api yet, so user is still undefined , the 2nd time is because you called setLogged(true) so user is still undefined , the 3rd and 4th times... i'm not sure, but you're probably changing the state somehow which causes a re-render

the proper wait to fix this, would be to wait until user is defined (ie the api call is finished), you can do that by using a simple if statement, something like

if (user.id) {
  // return components when the user is logged in
} else {
  // return components where the user is not logged in, usually a "loading" screen
}

Now you said user.id returns type error but i couldn't find any user.id in your code, so i assumed that you didn't post the whole thing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM