I built my react app.
I have 2 main folders. The first folder contains my react-app and the second contains my nodejs server. In the first file i've created 2 pages and i want to fetch data from nodejs server to one of my page from react app.
//Here is my nodejs file
var express = require('express');
var app = express();
app.post('/', function (req, res) {
res.send('POST request to the homepage');
});
app.listen(4000, function () {
console.log('Example app listening on port 4000!');
});
//Here is my react page where i want to fetch data from nodejs
import React, { useState, useEffect } from 'react';
const Home = () => {
useEffect(async function () {
const url = 'http://localhost:4000/';
const response = await fetch(url);
const data = await response.json();
console.log(data)
});
return(
<div>
<h1>Home Page</h1>
<p>{data}</p>
</div>
)
}
export default Home;
In the future i want to get data also from a nosql database using nodejs, but now I can't pass data from one node js file into reactjs file. How to do this?
Related
I'm trying to build a instagram scraper with puppeteer and react that works with putting the username on an input and then I want to show the scraped data on the console, I already built the puppeteer script and It works, it returns the data correctly, But I have some issues trying to get the data from a post with axios, I'm using node js and express for my server, when I try to do the post with axios I keep getting an error.
I want to write the username on the input, then I want the puppeteer script to run, and then I want to console log the data that the puppeteer script returns
Error on console
POST http://localhost:4000/api/getData/username_im_scraping net::ERR_CONNECTION_REFUSED
This is my code
Server > index.js
const path = require("path");
const express = require("express");
const webpack = require("webpack");
const cors= require('cors');
const webpackDevMiddleware = require("webpack-dev-middleware");
const webpackHotMiddleware = require("webpack-hot-middleware");
const config = require(path.join(__dirname, "../webpack.config.js"));
const compiler = webpack(config);
const app = express();
const { script } = require("./script");
app.use(webpackDevMiddleware(compiler, config.devServer));
app.use(webpackHotMiddleware(compiler));
app.use(express.static(path.join(__dirname, '../build')));
app.use(cors());
app.get("/api/getData/:username", async (req, res) => {
console.log(`starting script for user ${req.params.username}`);
const data = await script(req.params.username);
console.log(`stopping script for user ${req.params.username}`);
res.send(data);
});
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, '../build', 'index.html'));
});
app.listen(process.env.PORT || 4000, () => {
console.log('Server is listening on port 4000');
});
Homepage.js
import React, { useState } from "react";
import axios from "axios";
const Homepage = props => {
const [username, setUsername] = useState("");
const onChange = ({ target: { value } }) => setUsername(value);
const onClick = () => {
axios.post('http://localhost:4000/api/getData/' + username, {
header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;application/json' },
mode: "cors"
})
.then((response) => {
console.log(response);
})
.catch((error) => {
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log('Error', error.message);
}
})
};
return (
<div>
Time to start coding!
<input value={username} onChange={onChange} />
<button onClick={onClick}>Get instagram followers!</button>
</div>
);
};
export default Homepage;
The problem here is you defined your route with get like app.get("/api/getData/:username") but you are sending a post request. Either change the router to app.post or your axios method to axios.get.
UPDATE
Besides the changes above, after you shared the repository with me i checked and saw you have another problem, which was that you were not running your server so the ERR_CONNECTION_REFUSED message shown.
I forked your repository and made the following changes and created a PR for it. Please take a look at it, and if you want just merge it to your master branch.
P.S please for the next time create a .gitignore file and add node_modules to there so you don't push and pull your node_modules which takes some more amount of time.
I'm just learning Express/React and I'm trying to get set up with routes and basic database connections. I suspect I'm missing something very simple. I've tried to boil it down to the following.
Backend
server.js:
require('dotenv').config({path: '../.env'});
const mysql = require('mysql');
const express = require('express');
const bodyParser = require('body-parser');
const port = process.env.PORT || 5000;
const app = express();
const router = express.Router();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
const users = require('./routes/api/users');
app.use('/api/users', users);
const events = require('./routes/api/events');
app.use('/api/events', events);
const db = mysql.createConnection({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD
});
db.connect(function(err) {
if (err) throw err;
console.log('MySQL Connected!');
})
app.listen(port, () => console.log(`Listening on port ${port}`));
/routes/api/events.js:
const express = require('express');
const router = express.Router();
// GET api/events
router.get('/', (req, res) => {
res.send({id: "1", name: "hi"});
});
module.exports = router;
Frontend
App.js:
import React, { Component } from 'react';
import EventList from './components/EventList';
class App extends Component {
render() {
return (
<div className="App">
<EventList/>
</div>)
}
}
export default App;
/components/EventList.js:
import React, { Component } from 'react';
import axios from 'axios';
class EventList extends Component {
constructor() {
super();
this.state = {
events: []
}
}
componentDidMount() {
axios.get('/api/events')
.then(events => {
this.setState({events: events.data})
})
.catch(err => console.log(err))
}
render() {
var events = this.state.events;
return (
<div>
<p>Events:</p>
<ul>
{ events.map(({ id, name }) => (
<li>{name}</li>
))}
</ul>
</div>
)
}
}
export default EventList;
The error I get is http://localhost:3000/api/events 500 (Internal Server Error). What am I missing? I have truly scoured all of the docs I can find, but I'm not quite getting it.
Edit
I haven't changed anything, but now I'm getting a 404 (Not Found) instead. I had been getting a 500 for awhile, so it wasn't a momentary fluke. I'm not sure what could have changed.
Update
It may help to know that the .env variables I'm pointing to are actually for a remote MySQL database (i.e., DB_HOST != localhost, but a remote URL). Eventually, I'd like to connect the GET call on the events route to that db, but since it doesn't work with what I have here I figured my first issue to solve was upstream. As noted in comments, the PORT var I'm loading in is 3306. When I start the server, it says it's listening on 3306 as expected.
I think you are running your server on port 5000 and front on port 3000. if you request events with http://localhost:5000/api/events instead of /api/events, you would get 200 status code with your json data.
// as is
axios.get('/api/events')
// to be
axios.get('http://localhost:5000/api/events')
You could try typing componentDidMount function like this.
componentDidMount = async () =>{
//like this
}
In addition, I would recommend making the GET ALL its own function so you could just invoke in the componentDidMount function. whenever you run another CRUD action it will automatically update your events for you and instead of setting state every time you can invoke the this.getEvents() again to update it that way.
componentDidMount = async () =>{
this.getEvents()
}
Also you need to add this package (npm install cors) its so you can connect your api to your frontend.
Import it like this in your server.js file
const cors = require('cors')
app.use(cors())
You should add a proxy inside package.json in frontend like this.
"proxy": "http://localhost:5000",
I created a basic react app with Create React App. I removed all default files and added this into index file.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class App extends Component {
constructor() {
super();
this.state = {};
}
async componentDidMount() {
const response = await fetch('/express_backend');
const json = await response.json();
this.setState({ data: json.express });
}
render(){
return (
<div>{this.state.data}</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
This app works. I can add some letters between divs and it reloads when saving. But when I add simple Express server the reloading stops. I also add "proxy": "http://localhost:5000/" into package.json inside CRA to connect server and client
Here is the server
const express = require('express');
const app = express();
const port = 5000;
app.listen(port, () => console.log(`Listening on port ${port}`));
// create a GET route
app.get('/express_backend', (req, res) => {
res.send({ express: 'YOUR EXPRESS BACKEND IS CONNECTED TO REACT' });
});
I restarted both Create react app and server in console but now when I add smth between divs in the component nothing is reloading. I guess webpack dev server starts working improperly.
How can I make reloading in CRA work and make request to express each time when I change smth in component?
When running create-react-app with express, you'll need to run your server.js express app in a separate node process than the react-js-app. Also, you'll need to specify the proxy in your package.json.
Utilize these commands in separate terminals:
node server.js
and in separate terminal:
npm start
Kudos to this tutorial: https://dev.to/loujaybee/using-create-react-app-with-express
Basically to summarize my problem: I have some image to be displayed and it's displayed on localhost:5000 with status 200 where my Express server is running and when it comes to localhost:3000 i.e. my React Development Server, I made a request using Axios and it does give me gibberish and I don't know how to handle it at all.
React Code:
componentDidMount() {
axios.get('/filesuploaded/video_______82395d6a5af4e98fb8efca56f0ae3c1b_____.jpeg')
.then(Response => console.log(Response))
.catch(err => console.log(err));
}
Express Code:
route.get('/:filename' , (req , res) => {
GridFS.files.findOne({filename: req.params.filename} , (err , file) => {
const readstream = GridFS.createReadStream(file.filename);
readstream.pipe(res);
})
});
Random Gibberish:
{data: "����..."
SOLUTION:
So I played around more with the code and I had forgotten that this existed in my package.json of my client side and I have used it to full potential and rewrote my server side code without using multer anywhere.
Package.json:
"proxy": "http://localhost:5000" //This helps React communicate with ExpressJS through ports.
Server Side Config:
const route = require('express').Router();
const mongoose = require('mongoose');
const GridFS = require('gridfs-stream');
//Route for getting files
route.get('/file/:id' , (req , res) => {
//Setting Up GridFS-Stream
const db = mongoose.connection.db;
const MongoDriver = mongoose.mongo;
const gfs = new GridFS(db , MongoDriver);
const readstream = gfs.createReadStream({
_id: req.params.id,
});
//Reading to Response
readstream.pipe(res);
});
module.exports = route;
Front End Config:
import React, { Component } from 'react'
export default class Files extends Component {
//Render Method
render() {
return (
<div>
<img src = {window.location.pathname} alt = "something" />
</div>
)
}
}
Here the window.location.pathname will translate to /file/:id and send a GET request to ExpressJS, hence loading the image!
I am trying something simple where I make a request from the front-end and fetch the JSON data on the back-end. I'm using ReactJS on the front-end and NodeJS and ExpressJS on the Back-end.
I am getting little confused with figure what the right way how I can access JSON data onto the front-end by make the name server file name from server.js or con.now.
I am getting in my console not it refused to connect the link to the server. I have been tried to name the file server.js to cors.now would that connect the server to the front-end but I was wrong.
Failed to load resource: net::ERR_CONNECTION_REFUSED
But when every do that getting an error message in my console that talks about cors.now.sh/https://us-central1-aaronklaser-1.cloudfunctions.net/medium?username=#aaron.klaser
Medium.js
import React from 'react';
import PageHeader from './PageHeader';
import PageContent from './PageContent';
import axios from 'axios';
export default class Medium extends React.Component {
state = {
posts: []
}
componentDidMount() {
this.fetchPosts().then(this.setPosts)
}
fetchPosts = () => axios.get(`https://cors.now.sh/https://us-central1-aaronklaser-1.cloudfunctions.net/medium?username=#aaron.klaser`)
setPosts = response => {
this.setState({
posts: response
})
}
render() {
return (
<div>
<PageHeader/>
<PageContent>
<pre>{JSON.stringify(this.state.posts, null, 2)}</pre>
</PageContent>
</div>
)
}
}
cors.now
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
const request = require('request');
app.get("/api/medium", (req, res) => {
if(!req.query.username){
return res.status(400).send('Error: You need to include query param ?username=#yourUsername');
} else {
return request(url,(error, response, body) => {
const url = `https://medium.com/${req.query.username}/latest?format=json`;
const prefix = `])}while(1);</x>`
const strip = payload => payload.replace(prefix, ``)
res.send(JSON.parse(strip(body)));
});
}
});
app.listen(port, () => console.log(`Listening on port ${port}`));
I see you're using the https://cors.now.sh site as a reverse proxy. I am not sure if that site is functioning at this time?
If you hit your API endpoint directly (https://us-central1-aaronklaser-1.cloudfunctions.net/medium?username=#aaron.klaser) - I see a valid JSON response returned to the browser.
I believe the issue is with the reverse proxy site not running or responding at this time.