首页 > 解决方案 > 我的 REACT 应用程序出现路由问题

问题描述

好的,这是我的问题。我有这个 REACT 应用程序,到目前为止,当我在我的计算机上的本地主机上运行它时,我所拥有的一切运行良好。我将它部署在 Heroku,应用程序加载但反应与我的本地主机上的反应非常不同。这是发生了什么。

在我的本地主机上,当应用程序加载主页时,在导航栏上,有几个选项可供选择,包括门票。如果您单击门票选项,它会加载门票页面。从那里,在页面的左侧,您可以选择输入新票证并将其保存到 Mongo 数据库。在页面的右侧,它列出了所有当前已输入并存储在 Mongo 数据库中的票证。您可以单击其中一张工单以查看工单详细信息,或者您还可以选择从数据库中删除工单。就像我说的,在本地运行一切正常。

问题是,当我从 Heroku 加载部署的版本时,它会加载主页,但是当我单击导航栏中的票证选项时,它没有加载票证页面,它只返回 JSON 格式的所有取消票证. 它实际上为导航栏上的所有选项(客户、材料和票证)执行此操作。我一直在弄乱我的路线试图找到问题并且没有成功。我有点猜测/希望这是我缺少的一些简单的东西,但我的部分问题是,我有很多代码,我不确定我需要在这里发布什么。所以我要发布我的 Server.js 和一些路线,我想从那里开始。

服务器.js

require('dotenv').config();

const express = require('express');
const mongoose = require('mongoose');
const routes = require("./routes");
const app = express();

const port = process.env.PORT || 3030;

const customers = require('./routes/api/Customers');
const materials = require('./routes/api/Materials');
const tickets = require('./routes/api/Tickets');

app.use(express.urlencoded({ extended: true }));
app.use(express.json());

if (process.env.NODE_ENV === "production") {
  app.use(express.static("client/build"));
}

const DB = process.env.DB;

// app.use('/', customers);/
app.use('/customers', customers);
app.use('/materials', materials)
app.use('/tickets', tickets)

mongoose
  .connect(DB,{ useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false})
  .then(() => console.log('MongoDB Connected!'))
  .catch(err => console.log(err));
  
app.listen(port, () => console.log(`Server started on port ${port}`));

路线>api>index.js

const path = require("path");
const router = require("express").Router();
const apiRoutes = require("./api");


// API Routes
router.use("/api", apiRoutes);


// If no API routes are hit, send the React app
router.use(function(req, res) {
  res.sendFile(path.join(__dirname, "../client/build/index.html"));
});

module.exports = router;

路线>api>Tickets.js

onst express = require('express');
const router = express.Router();

const ticketController = require('../../controllers/ticket');

router.route('/')
  .get(ticketController.index)
  .post(ticketController.newTicket);

router.route('/:ticketID')
  .get(ticketController.getTicket)
  .put(ticketController.replaceTicket)
  .patch(ticketController.updateTicket)
  .delete(ticketController.removeTicket);

module.exports = router;

这是来自 React 应用程序的代码:

API.js

import axios from "axios";

export default { 
   // Gets all tickets
   getTickets: function() {
     return axios.get("/Tickets");
  },
  // Gets the ticket with the given id
  getTicket: function(id) {
    return axios.get("/Tickets/" + id);
  },
  
  // Deletes the ticket with the given id
  deleteTicket: function(id) {
    return axios.delete("/Tickets/" + id);
  },
  // Saves a ticket to the database
  saveTicket: function(ticketData) {
    return axios.post("/Tickets", ticketData);
  },
   // Gets all Customers
   getCustomers: function() {
     return axios.get("/Customers");
  },
  // Gets the customer with the given id
  getCustomer: function(id) {
    return axios.get("/Customers/" + id);
  }, 

  getCustLocations: function(id) {
    return axios.get("/Customers/" + id + "/locations");
  },
  
  
  // Deletes the customer with the given id
  deleteCustomer: function(id) {
    return axios.delete("/Customers/" + id);
  },
  // Saves a customer to the database
  saveCustomer: function(customerData) {
    return axios.post("/Customers", customerData);
  },
 // Gets all Materials
  getMaterials: function() {
    return axios.get("/Materials");
  },
  // Gets the Material with the given id
  getMaterial: function(id) {
    return axios.get("/Materials/" + id);
  },
  // Deletes the Material with the given id
  deleteMaterial: function(id) {
    return axios.delete("/materials/" + id);
  },
  // Saves a Material to the database
  saveMaterial: function(materialData) {
    return axios.post("/materials", materialData);
  },

};

门票.js

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([])
  const [materials, setMaterials] = 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));
  };

  // Load all materials and store them with setMaterials
  useEffect(() => {
    loadMaterials()
  }, [])

  // Loads all materials and sets them to customers
  function loadMaterials() {
    API.getMaterials()
    .then(res =>
      setMaterials(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,
        ticketMaterial: formObject.ticketMaterial,
        ticketTareWeight: formObject.ticketTareWeight,
        ticketGrossWeight: formObject.ticketGrossWeight,
        ticketNetWeight: formObject.ticketGrossWeight - formObject.ticketTareWeight
      })
        .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"
              style={{width: '100%', height: 35, marginBottom: 15}}>
              {customers.map((customers, ii ) => (
              <> 
               <option key={ii} value="" hidden>Select Customer</option>
               <option key={customers.custName}>{customers.custName}</option>  
              </>   
              ))}
            </select>
            <select onChange={handleInputChange}
              name="ticketMaterial"
              style={{width: '100%', height: 35, marginBottom: 15}}>
              {materials.map((materials, ii ) => (
              <> 
               <option key={ii} value="" hidden>Select Material</option>
               <option key={materials._id}>{materials.name}</option>  
              </>   
              ))}
            </select>
            <Input
              onChange={handleInputChange}
              name="ticketTareWeight"
              placeholder="Tare Weight"
            /> 
            <Input
              onChange={handleInputChange}
              name="ticketGrossWeight"
              placeholder="Gross Weight"
            />          
            <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;

APP.js

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import NavBar from './components/NavBar';
import Tickets from './components/pages/Tickets';
import TicketDetails from './components/pages/TicketDetails';
import Customers from './components/pages/Customers';
import CustomerDetails from './components/pages/CustomerDetails';
import Materials from './components/pages/Materials';
import MatDetails from './components/pages/MatDetails';


import 'bootstrap/dist/css/bootstrap.min.css';
import '../src/components/App.css';

function App()  {
  return (
    <Router>
      <div>
        <NavBar/>
        <Switch>
          <Route exact path={"/tickets"}>
            <Tickets />
          </Route>
          <Route exact path={"/tickets/:id"}>
            <TicketDetails />
          </Route>
          <Route exact path={"/customers"}>
            <Customers />
          </Route>
          <Route exact path={"/customers/:id"}>
            <CustomerDetails />
          </Route>          
          <Route exact path={"/materials"}>
            <Materials />
          </Route>
          <Route exact path={"/materials/:id"}>
            <MatDetails />
          </Route>

        </Switch>
      </div>
    </Router>
  );
}

export default App;

导航栏.js

import React, { useState } from 'react';
import {
  Collapse,
  Navbar,
  NavbarToggler,
  NavbarBrand,
  Nav,
  NavItem,
  NavLink,
  NavbarText
} from 'reactstrap';

const NavBar = (props) => {
  const [isOpen, setIsOpen] = useState(false);

  const toggle = () => setIsOpen(!isOpen);

  return (
    <div>
      <Navbar color="dark" dark expand="md">
        <NavbarBrand href="/">HAMMER</NavbarBrand>
        <NavbarToggler onClick={toggle} />
        <Collapse isOpen={isOpen} navbar>
          <Nav className="mr-auto" navbar>
            <NavItem>
              <NavLink href="/Tickets">Tickets</NavLink>              
            </NavItem>
            <NavItem>
              <NavLink href="/Customers">Customers</NavLink>
            </NavItem>
            <NavItem>
              <NavLink href="/Materials">Materials</NavLink>
            </NavItem>
          </Nav>
          <NavbarText >Nathan Huber</NavbarText>
        </Collapse>
      </Navbar>
    </div>
  );
}

export default NavBar;

我很感激任何帮助!

谢谢,

弥敦道

标签: javascriptnode.jsreactjsmongodbexpress

解决方案


原来,我的构建文件夹有问题。我还编辑了我的 server.js 文件。我变了:

if (process.env.NODE_ENV === "production") {
  app.use(express.static("client/build"));
}

至:

if (process.env.NODE_ENV === "production") {
  app.use(express.static("client/build"));
  app.get("/*", function(req, res) {
    res.sendFile(path.join(__dirname, "./client/build/index.html"));
  });
}

else {
  app.use(express.static(path.join(__dirname, '/client/public')));
  app.get("/*", function(req, res) {
    res.sendFile(path.join(__dirname, "./client/public/index.html"));
  });
}

这似乎纠正了我的路线问题,但似乎也打开了一个全新的蠕虫罐头,哈哈。现在,当我单击导航栏中的门票链接时,它似乎打开了门票页面,但随后它消失并引发了一堆错误。我假设路由器正在工作,因为它至少开始打开页面。如果需要,我将处理这些新错误并提交一个新问题。

谢谢您的帮助。

-N8


推荐阅读