Почему информация, которую я получаю от моего бэкэнда, получает console.logged, но не отображается в React? - PullRequest
0 голосов
/ 03 августа 2020

Мое приложение состоит из следующего: Это приложение, использующее стек MERN, цель которого - предоставить пользователям возможность входить в систему, регистрироваться и просматривать контакты. (Это просто для практики, у меня нет планов по его развертыванию).

Проблема возникает, когда Пользователь входит в систему, а затем переходит к контактам, я могу их console.log, получая их из Express в задней части, но я не могу их отобразить. Вдобавок ко всему, когда я console.log длину, он говорит 0, хотя когда я console.log массив, он показывает элементы, и это то, что я не могу понять.

Вот приложение. 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 Router, и вот, во-первых, регистр. 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;

Вот логин. 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>
  )
}

И, наконец, вот my 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 l oop не работает, и я понятия не имею, почему, потому что, когда я печатаю массив контактов, я получаю их полностью.

Вот что получаю в консоли:

Результаты console.logging массива контактов и его длина

Я не предоставляю файлы из бэкэнда, потому что, как вы можете видеть, проблема явно во внешнем интерфейсе, потому что я получаю данные, но не отображаю их правильно.

1 Ответ

0 голосов
/ 03 августа 2020

Вы можете просто попробовать .map функцию массива.

Обычные шаблоны -

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

Как упоминалось в @Gandzal, .forEach будет l oop каждые значение внутри массива, но оно ничего не вернет, тогда как .map вернет массив.

В вашем случае .map вернет массив элементов JSX.

Примечание: вы можете замените JSON .string, указав весь объект на contact.id или contact.emailContact, как вы wi sh.

...