Videos
hi so basically I have been using express generator to make new express apps. I can make servers and then endpoint routes and then I then render html files for each of the routes visited and i use PUG as the view engine.
app.set("views", path.join(__dirname, "../views"));app.set("view engine", "pug");
Pug is nice but I am trying to figure out how to use react instead of making views for every route. Also as far as styling, using express generator I seem to only be able to edit styles.css to write vanilla css and then I have to serve the static path.
app.use(express.static(path.join(__dirname, "../public")));
In a nutshell, I am just trying to figure out how to use react with nodejs and express. I read a couple of guides so I think I have the directory structure correct (client and server, each with their own node modules), but not sure on how to proceed. any advice? I've attached my repo. thanks.
https://github.com/ForkEyeee/blog-api
There were a few errors. Here is some updated code and a description of what was going on:
React App.js:
import React, { Component } from 'react';
import axios from 'axios';
class Create extends Component {
constructor(props) {
super(props);
this.state = {
bookID: '',
bookTitle: '',
bookAuthor: '',
};
}
handleInputChange = e => {
this.setState({
[e.target.name]: e.target.value,
});
};
handleSubmit = e => {
e.preventDefault();
const { bookID, bookTitle, bookAuthor } = this.state;
const book = {
bookID,
bookTitle,
bookAuthor,
};
axios
.post('http://localhost:3001/create', book)
.then(() => console.log('Book Created'))
.catch(err => {
console.error(err);
});
};
render() {
return (
<div>
<br />
<div className="container">
<form onSubmit={this.handleSubmit}>
<div style={{ width: '30%' }} className="form-group">
<input
type="text"
className="form-control"
name="bookID"
placeholder="Book ID"
onChange={this.handleInputChange}
/>
</div>
<br />
<div style={{ width: '30%' }} className="form-group">
<input
type="text"
className="form-control"
name="bookTitle"
placeholder="Book Title"
onChange={this.handleInputChange}
/>
</div>
<br />
<div style={{ width: '30%' }} className="form-group">
<input
type="text"
className="form-control"
name="bookAuthor"
placeholder="Book Author"
onChange={this.handleInputChange}
/>
</div>
<br />
<div style={{ width: '30%' }}>
<button className="btn btn-success" type="submit">
Create
</button>
</div>
</form>
</div>
</div>
);
}
}
export default Create;
- You were getting errors for using
classand notclassName.classis a reserved word in react.js and should not be used. - You were using the default post method which I would not recommend. I split the post out into it's own action and used the common library
axiosto make the CORS post call. I also created a function to handle the input changing on every key press with react.js. - I added
stateto your component. This is common when there are form inputs to store them instate. I also changed the name of your variables to be title case which is the common way to write code variables.
Node.js index.js:
const express = require('express');
const logger = require('morgan');
const cors = require('cors');
const app = express();
//use cors to allow cross origin resource sharing
app.use(
cors({
origin: 'http://localhost:3000',
credentials: true,
})
);
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
let books = [];
app.get('/home', function(req, res) {
console.log('Inside Home Login');
res.writeHead(200, {
'Content-Type': 'application/json',
});
console.log('Books : ', JSON.stringify(books));
res.end(JSON.stringify(books));
});
app.post('/create', function(req, res) {
const newBook = {
BookID: req.body.bookID,
Title: req.body.bookTitle,
Author: req.body.bookAuthor,
};
books.push(newBook);
console.log(books);
});
//start your server on port 3001
app.listen(3001, () => {
console.log('Server Listening on port 3001');
});
- You weren't parsing the body of the req, so it was coming back as
undefined. I added
app.use(express.json());andapp.use(express.urlencoded({ extended: false }));which should take care of most of the issues. - I updated the
req.bodyvariables to match those coming over from React. - I added the module
morgenwhich you see hereapp.use(logger('dev'));this is helpful by showing all your requests and statuses for dev purposes. In this case, it was showing that you were getting a 500 (internal server error) because express couldn't readbookIDofundefined(because the body wasn't being parsed).
This should be working now, let me know if you have any problems.
I don't use express some so the details may not apply.
In essence you will have to send a network request to your server. How you do this is up to you, The most common ways are with axios(a library) or with vanilla js with the fetch api.
I would just use the fetch api. it takes two parameters an url and the options. so it should be called like this fetch(url,options)
so in your case it would be fetch('localhost:3001/create, options)
What should be in the options. I just suggest you look at the fecth MDN docs here https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
but your case you will need to pass an object with the method property set to post and the new book you want to data property set to a JSON serialized object of the book you want to create.
for example
let book ={
BookId:1,
Title: "coolBook",
Author: "Me"
}
fetch("localhost:3001/create",
{
method: "post",
data: JSON.stringify(book)
}
When passing the books a string instead of an object you will likely have to take that string and parse it as an object on the server so that you express /create handler looks more like:
app.post('/create', function (req, res) {
var newBook = JSON.parse(req.body.data)
books.push(newBook)
console.log(books);
})
On the react side you need to create an event handler that calls the above fetch function. I recommend you watch a react/express tutorial though as I can;t really cover all the thing required here in a stack overflow question such as: using and validating forms in react, error handling, async/await and so on.
All the Best! hope that was slightly helpful