首页 > 解决方案 > 我的 console.log() 应该运行 3 次吗?

问题描述

下面是我的组件页面之一的代码。就是将一些票据数据输入到 MongoDB 数据库中。我正在尝试通过在下拉框中选择客户名称来自行填充客户信息。我在第 18 行放置了一个 console.log() ,只是为了看看我是否能弄清楚客户集合中的数据是在什么时候设置的。当我在第 18 行有 console.log() 时,它会出现 3 次。前两次它记录一个空数组,但第三次它有来自 MongoDB 的数据。我对编码很陌生,我有点困惑为什么 console.log 会运行 3 次。我对发布我的代码有点害羞,因为我仍然很清楚我确信我做错了各种各样的事情,但是有人可以在正确的方向上引导我吗?它应该运行多次吗?此外,我收到以下警告,我无法弄清楚:

警告:列表中的每个孩子都应该有一个唯一的“关键”道具。

Check the render method of `Tickets`. See https://reactjs.org/docs/lists-and-keys.html#keys for more information.
    in Fragment (created by Tickets)
    in Tickets (at App.js:22)
    in Route (at App.js:21)
    in Switch (at App.js:20)
    in div (at App.js:18)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:17)
    in App (at src/index.js:6)

我知道这与我在第 97 行的下拉选择有关,但我似乎无法弄清楚如何让它快乐。

import React, { useState, useEffect } from "react";
import DeleteBtn from "../DeleteBtn";
import Jumbotron from "../Jumbotron";
import API from "../../utils/API";
import { Link } from "react-router-dom";
import { Col, Row, Container } from "../Grid";
import { List, ListItem } from "../List";
import { Input, FormBtn } from "../Form";

const moment = require('moment');

function Tickets(props) {
  // Setting our component's initial state
  const [tickets, setTickets] = useState([])
  const [formObject, setFormObject] = useState({})
  const [customers, setCustomers] = useState([])

  console.log("Customer = ", customers)

  // Load all tickets and store them with setTickets
  useEffect(() => {
    loadTickets()
  }, [])

  // Loads all tickets and sets them to tickets
  function loadTickets() {
    API.getTickets()
      .then(res => 
        setTickets(res.data)
      )
      .catch(err => console.log(err));
  };  

  // Load all Customers and store them with setCustomer
  useEffect(() => {
    loadCustomers()
  }, [])

  // Loads all customers and sets them to customers
  function loadCustomers() {
    API.getCustomers()
    .then(res =>
      setCustomers(res.data)
    )
    .catch(err => console.log(err));
  };

  // Deletes a ticket from the database with a given id, then reloads tickets from the db
  function deleteTicket(id) {
    API.deleteTicket(id)
      .then(res => loadTickets())
      .catch(err => console.log(err));
  }

 // Handles updating component state when the user types into the input field
 function handleInputChange(event) {
   const { name, value } = event.target;
   setFormObject({...formObject, [name]: value})
 };

 // When the form is submitted, use the API.saveTicket method to save the ticket data
// Then reload tickets from the database
  function handleFormSubmit(event) {
    event.preventDefault();
    if (formObject.ticketDate) {
      API.saveTicket({
        ticketDate: formObject.ticketDate,
        ticketNum: formObject.ticketNum,
        ticketCust: formObject.ticketCust,
        ticketCustStreet: formObject.ticketCustStreet
      })
        .then(res => loadTickets())
        .catch(err => console.log(err));
        document.getElementById("ticketFrm").reset();  
        setFormObject({})      
    }
  };

  return (
    <Container fluid>
      <Row>
        <Col size="md-6">
          <Jumbotron>
            <h1>Add Ticket</h1>
          </Jumbotron>
          <form id="ticketFrm">
            <Input
              onChange={handleInputChange}
              name="ticketDate"
              placeholder="Date"
            />
            <Input
              onChange={handleInputChange}
              name="ticketNum"
              placeholder="Ticket Number (required)"
            />          
            <select onChange={handleInputChange}
              name="ticketCust"
              placeholder= "Customer Name"
              style={{width: '100%', height: 35, marginBottom: 15}}>
              {customers.map(customers => (
               <> 
               <option value="" hidden>Select Customer</option>
               <option default="Customer" key={customers._id}>{customers.custName}</option>  
              </>   
              ))}
            </select>
            <Input
              onChange={handleInputChange}
              name="ticketCustStreet"
              placeholder="Street"
            /> 
            <Input
              onChange={handleInputChange}
              name="ticketCustCity"
              placeholder="City"
            /> 
            <Input
              onChange={handleInputChange}
              name="ticketCustState"
              placeholder="State"
            /> 
            <Input
              onChange={handleInputChange}
              name="ticketCustZip"
              placeholder="Zip"
            /> 
            <Input
              onChange={handleInputChange}
              name="ticketCustMaterial"
              placeholder="Material"
            /> 
            <FormBtn
              disabled={!(formObject.ticketNum)}
              onClick={handleFormSubmit}>
              Submit Ticket
            </FormBtn>
          </form>
        </Col>
        <Col size="md-6 sm-12">
            <Jumbotron>
              <h1>Current Tickets</h1>
            </Jumbotron>
            {tickets.length ? (
              <List>
                {tickets.map(tickets => (
                  <ListItem key={tickets._id}>
                    <Link to={"/Tickets/" + tickets._id}>
                      <strong>
                      Ticket Date - {moment(tickets.ticketDate).format("MM-DD-YYYY")}
                        <br></br>
                      Ticket# - {tickets.ticketNum}
                      <br></br>
                      {tickets.ticketCust}
                      </strong>
                    </Link>
                    <DeleteBtn onClick={() => deleteTicket(tickets._id)}/>
                  </ListItem>
                ))}
              </List>
            ) : (
              <h3>No Results to Display</h3>
            )}
          </Col>
        </Row>
      </Container>
    );
}

export default Tickets;

感谢您的任何意见,请不要对我的代码过于苛刻地评判我。

谢谢,

-N8

标签: javascriptnode.jsreactjsmongodbmongoose

解决方案


useEffect在组件安装到 DOM 后,将调用您的钩子。正在使用未定义的数据调用第一个控制台日志(因为尚未进行调用)

关于Warning: Each child in a list should have a unique "key" prop.. 键帮助 React 识别哪些项目已更改、添加或删除。应为数组内的元素提供键,以使元素具有稳定的身份。选择键的最佳方法是使用一个字符串,该字符串在其兄弟项中唯一标识一个列表项。大多数情况下,您会使用数据中的 ID 作为键。当您没有渲染项目的稳定 ID 时,您可以使用项目索引作为键作为最后的手段。

https://reactjs.org/docs/lists-and-keys.html

所以要删除你的警告,我会做类似的事情

{customers.map((customers, ii) => (
               <> 
               <option value="" key={ii} hidden>Select Customer</option>
               <option default="Customer" key={customers._id}>{customers.custName}</option>  
              </>   
              ))}

推荐阅读