0

我的应用程序包括以下内容: 这是一个使用 MERN 堆栈的应用程序,目标是让用户能够登录、注册和查看联系人。(这只是为了练习,我没有部署它的计划)。

当用户登录时出现问题,然后转到联系人,我可以控制台记录它们,从后端的 Express 获取它们,但我无法显示它们。最重要的是,当我 console.log 长度时,它显示为 0,即使当我 console.log 数组显示项目时,它也是我无法理解的。

这是 App.js

// Importing React
import React from 'react';

// Importing the Router
import { BrowserRouter as Router, Switch, Route} from "react-router-dom";

// Get Login Functional Component
import Register from "./Register";

// Get the Register FC
import LogIn from "./LogIn";

// Get the Contacts FC
import Contacts from "./Contacts";

// Get the USER Context
import {UserContextProvider} from "./Context/UserContext";


function App() {
  return (
    <UserContextProvider>
        <Router>
          <div className="App">
            <Switch>
              <Route exact path="/register" component={Register} />
              <Route exact path="/login" component={LogIn} />
              <Route exact path="/contacts" component={Contacts} />
            </Switch>
          </div>
        </Router>
      </UserContextProvider>
  );
}

export default App;

如您所见,我正在使用 React 路由器,这里首先是 Register.js

import React, {useState} from 'react';
import axios from "axios";
import {Link} from "react-router-dom";

function Register() {

  // Getting Email Input with UseState
  const [email, setEmail] = useState("");

  // Getting Password Input with UseState
  const [password, setPassword] = useState("");

  // Getting Confirmation Password Input with UseState
  const [confirmationPassword, setConfirmationPassword] = useState("");

  // If passwords are matching
  const [passwordsMatch, setPasswordsMatch] = useState("");

  // To Clear Input Fields
  const clearFields = () => {setEmail(""); setPassword("");}

  // Function that changes the email state when the user types
  const changeEmail = (e) => {
    setEmail(e.target.value);
  }
  // Function that changes the password state when the user types
  const changePassword = (e) => {
    setPassword(e.target.value);
  }

  // Function that changes the confirmation password state when the user types
  const changeConfirmationPassword = (e) => {
    setConfirmationPassword(e.target.value);
  }

  // When the user submits the form
  const registerSubmit = (e) => {
    
    // So it doesn't go to another page
    e.preventDefault();

    if (password === confirmationPassword) {
      setPasswordsMatch(true);

      // Passing data to backend
      axios.post("http://localhost:5000/post", {email, password})
      .then(response => console.log(response))
      .catch(error => console.log(error.data));

      // Clear all the fields
      clearFields();
    } else {
      setPasswordsMatch(false);
    }
  }

  return (
    <div>
      <div className="container mt-4">
        <form onSubmit={(e) => registerSubmit(e)}>
          <div className="form-group">
            <label htmlFor="exampleInputEmail1">Email address</label>
            <input type="email" className="form-control" onChange={(e) => changeEmail(e)} id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email" value={email}></input>
            <small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
          </div>
          <div className="form-group">
            <label htmlFor="exampleInputPassword1">Password</label>
            <input onChange={(e) => changePassword(e)} type="password" className="form-control" id="exampleInputPassword1" placeholder="Password" value={password}></input>
          </div>
          <div className="form-group">
            <label htmlFor="exampleInputPassword2">Confirm Password</label>
            <input onChange={(e) => changeConfirmationPassword(e)} type="password" className="form-control" id="exampleInputPassword12" placeholder="Password" value={confirmationPassword}></input>
            {/* If Passwords Match then Show Alert */}
            {passwordsMatch === false && 
              <div className="alert alert-danger mt-4" role="alert">
                Passwords don't match!
              </div>
            }
          </div>
          <button type="submit" className="btn btn-primary">Register</button>
        </form>
        <h5 className="mt-4 mb-4">If you already have an account</h5>
        <Link to={"/login"} className="btn btn-secondary">I already have an account</Link>
      </div>
    </div>
  )
}

export default Register;

这是 LogIn.js:

import React, {useState, useContext, history} from 'react';
import {Link} from "react-router-dom";
import axios from "axios";

// Get User Context
import {UserContext} from "./Context/UserContext";

function LogIn() {
  // Getting the ID from the context
  const {id, setId} = useContext(UserContext);

  // Getting Email Input with UseState
  const [email, setEmail] = useState("");

  // Getting Password Input with UseState
  const [password, setPassword] = useState("");

  const [logIn, setLogIn] = useState(undefined);

  // Function that changes the email state when the user types
  const changeEmail = (e) => {
    setEmail(e.target.value);
  }
  // Function that changes the password state when the user types
  const changePassword = (e) => {
    setPassword(e.target.value);
  }

  // When the user submits the form
  const onLoginSubmit = (e) => {

    // So it doesn't go to another page
    e.preventDefault();

    // Check Credentials
    axios.get("http://localhost:5000")
    .then(response => { for (const index in response.data) {
      const person = response.data[index];
        if (person.email === email && person.password === password) {
          // User has succesfully logged in
          setLogIn(true);
          // Store Secret ID in variable
          const secretID = person._id;
          // Change Context
          setId(secretID);
          // Break the loop
          break;
        } else {
          setLogIn(false);
        }
      };
    })
    .catch(error => console.log(error.data));
  }

  return (
    <div>
      <div className="container mt-4">
        <form onSubmit={(e) => onLoginSubmit(e)}>
          <div className="form-group">
            <label htmlFor="exampleInputEmail1">Email address</label>
            <input type="email" className="form-control" onChange={(e) => changeEmail(e)} id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email" value={email}></input>
            <small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
          </div>
          <div className="form-group">
            <label htmlFor="exampleInputPassword1">Password</label>
            <input onChange={(e) => changePassword(e)} type="password" className="form-control" id="exampleInputPassword1" placeholder="Password" value={password}></input>
          </div>
          <button type="submit" className="btn btn-primary">Log In</button>
        </form>
        {logIn === false && 
          <div className="alert alert-danger mt-4" role="alert">
            Wrong credentials!
          </div>
        }
        {logIn === true &&
          <div className="alert alert-success mt-4" role="alert">
            Correct information!
          </div>
        }
        <h5 className="mt-4 mb-4">If you don't have an account</h5>
        <Link to={"/register"} className="btn btn-secondary">I don't have an account</Link>
        {logIn && <Link to={"/contacts"} className="btn btn-secondary ml-4">Contacts</Link>}
      </div>
    </div>
  )
}

export default LogIn;

在这里您可以看到我正在使用 Context Hook,这是我创建它的文件 (UserContext.js):

import React, {createContext, useState} from 'react'

export const UserContext = createContext();

export function UserContextProvider(props) {

  // Create the ID variable
  const [id, setId] = useState("");

  return (
    <UserContext.Provider value={{id, setId}}>
      {props.children}
    </UserContext.Provider>
  )
}

最后,这是我的 Contact.js:

import React, {useContext, useState} from 'react';
import {UserContext} from "./Context/UserContext";
import axios from "axios";

// To display single contacts
import SingleContact from "./SingleContact";

function Contacts() {
  const {id, setId} = useContext(UserContext);

  const [email, setEmail] = useState("");

  const contacts = [];


  // Get User's Info from database
     // Check Credentials
     axios.get("http://localhost:5000/contacts")
     .then(response => { for (const index in response.data) {
       const contact = response.data[index];
         if (contact.id === id) {
           contacts.push(contact);
         }
       };
     })
     .catch(error => console.log(error.data));


  return (
    <div>
      <h1>Contacts</h1>
      {console.log(contacts)}
      {console.log(contacts.length)}
      {contacts.forEach(contact => <h1>{contact}</h1>)}
    </div>
  )
}

export default Contacts

在这里,forEach 循环不起作用,我不知道为什么,因为当我打印联系人数组时,我完全得到了它们。

这是我在控制台中得到的:

console.logging 联系人数组及其长度的结果

我没有从后端提供文件,因为如您所见,问题显然出在前端,因为我正在获取数据,但没有正确显示它。

4

1 回答 1

0

您可能只想尝试.map数组的功能。

通常的模式——

return (
    <div>
      <h1>Contacts</h1>
      {contacts.map((contact,index) => <h1 key={index}>{JSON.stringify(contact)}</h1>)}
    </div>
  )

正如@Gandzal 提到的,.forEach将循环数组中的每个值,但它不会返回任何内容,而.map会返回一个数组。

在您的情况下,.map将返回 JSX 元素数组。

注意:您可以根据需要将整个对象的 JSON.stringifying 替换为 contact.id 或 contact.emailContact。

于 2020-08-03T16:29:40.613 回答