Окончательные результаты:
Объяснение:
Итак, даже при локальном запуске я получал 404 - проблема заключалась в том, как вы запускали приложение.
Вам нужно только запустить сервер, а не клиент. Похоже, вы запускаете «встроенный» сервер, который поставляется с create-react-app
... так что ваш сервер никогда не принимал запросы, так как ваш интерфейс работал на порту 3000, а ваш сервер работал на том порту, который у вас был установить в .env
.
Из-за того, что вы axios
отправляете запросы (просто используя текущий URL, который работал на встроенном порту create-react-app
, а не на порту вашего сервера), он по сути отправлял запросы на неправильный порт .
Это то, о чем я должен был подумать вчера вечером, так как я вспомнил, что видел, как ваше приложение Heroku использовало сборку разработки React (через расширение Firefox React) - это должен был быть красный флаг.
Я добавил 2 новых npm
скрипта: npm run begin
и npm start
(переименовал оригинал npm start
в npm run start:original
. npm run begin
, правильно строит ваш интерфейс, а затем запускает ваш бэкэнд . В конечном итоге это и решило проблему . У меня также было NODE_ENV=production
при локальном тестировании.
Я также удалил npm heroku-postbuild
, так как он не нужен.
Изменения кода:
После того, как это сработало, я заметил, что с вашим интерфейсным кодом что-то не так - al oop отправлял запрос снова и снова - я продолжал видеть ниже информация записывается на консоль. Поэтому я также решил, что используя код ниже (я не удалял код, я просто закомментировал код, чтобы вы могли видеть сделанные мной изменения).
Я не знаю, где вы ' Я использую Mon go в, но я протестировал это с помощью Atlas - у меня были проблемы с базой данных после развертывания в Heroku, поэтому мне также пришлось изменить способ подключения к базе данных в server.js
. Вы также можете просмотреть эти изменения ниже или в репозитории GitHub.
Дайте мне знать, если вы хотите, чтобы я отправил запрос на извлечение в ваш репозиторий, чтобы у вас был обновленный код, и вам не нужно будет вручную измените что-либо.
Наконец, дважды проверьте переменные среды внутри Heroku - убедитесь, что они установлены.
// This kept being logged to the console
...
actually hit the route
actually hit the route
actually hit the route
actually hit the route
actually hit the route
actually hit the route
...
...
// This kept going on and on and on after I searched
Это изменения, которые я сделал, чтобы исправить запрос л oop:
// App.js
function App() {
/**
* Separated your state into 2 different variables.
* Your request loop was happening due to how your
* useEffect was configured (specifically the dependency
* array)
*/
const [searchTerm, setSearchTerm] = useState();
const [searchResults, setSearchResults] = useState();
/*
const [search, setSearch] = useState({
term: '',
results: []
});
*/
useEffect(() => {
Axios.post(`/api/search`, { term: searchTerm /* search.term */ })
.then(books => {
setSearchResults(books.data);
// setSearch({...search, results: books.data})
});
}, [searchTerm]);
return (
<div className="app">
<Header />
<Router>
<Route exact path='/'>
<Searchbar /* search={search} <-- No need for this param */ setSearch={setSearchTerm} />
{!searchTerm /* search.term */ ? (
<div className="message">
<p>Search for a book or whatever</p>
</div>
) : <SearchList results={searchResults/* search.results */} />}
</Route>
<Route path='/saved'>
<h2 className="title">Saved Books</h2>
<SavedList />
</Route>
<Footer />
</Router>
</div>
);
}
// Searchbar.js
const Searchbar = ({/* search, */ setSearch}) => { // <-- No need for search param here
return (
<form action="#" method="get" className="searchbar" onSubmit={e => e.preventDefault()}>
<DebounceInput
minLength={2}
debounceTimeout={300}
type="search"
placeholder="? search..."
onChange={(e) => setSearch(e.target.value)}
/>
</form>
)
}
// server.js
require('dotenv').config();
const express = require('express');
const path = require('path');
const Axios = require('axios');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const PORT = process.env.PORT || 8080;
const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/book';
const app = express();
// Define middleware here
app.use(express.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Serve up static assets (usually on heroku)
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
}
const { Schema } = mongoose;
const bookSchema = new Schema({
info: Schema.Types.Mixed,
});
// *** REMOVED THIS ***
// const Book = mongoose.model('Book', bookSchema);
// ==========================================================
// **********************************************************
// CHANGED THE WAY YOU CONNECT TO MONGO
// **********************************************************
// ==========================================================
/** */ mongoose.set('useCreateIndex', true);
/** */
/** */ const mongoConnection = mongoose.createConnection(mongoUri, {
/** */ useUnifiedTopology: true,
/** */ useNewUrlParser: true,
/** */ useFindAndModify: false,
/** */ });
/** */
/** */ const Book = mongoConnection.model('Book', bookSchema /*, 'COLLECTION_NAME'*/);
// ==========================================================
// **********************************************************
// END OF CHANGES
// **********************************************************
// ==========================================================
app.post('/api/search', (req, res) => {
console.log('actually hit the route');
Axios.get(
`https://www.googleapis.com/books/v1/volumes?q=${req.body.term}`
).then(books => res.json(books.data.items));
});
app.post('/api/save', (req, res) => {
const newBook = new Book({ info: req.body.book });
newBook.save(err => {
if (err) res.json(err);
res.json({ status: true });
});
});
app.post('/api/unsave', (req, res) => {
Book.findByIdAndRemove(req.body.book._id, err => {
if (err) res.json(err);
res.json({ status: true });
});
});
app.get('/api/saved', (req, res) => {
Book.find({}, (err, books) => {
if (err) res.json(err);
else res.json(books);
});
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, './client/build/index.html'));
});
/*
const db = mongoose.connection;
db.on('error', // console.error.bind(console, 'connection error:')
error => {
console.log("[MONGOOSE][ERROR]", error);
}
);
db.once('open', function() {
console.log('[MONGOOSE][SUCCESS] Connected to database!');
});
*/
app.listen(PORT, () => {
console.log(`? ==> API server now on port ${PORT}!`);
});