How to retrieve data from reactjs and API - javascript

I am trying to post form data from react to node backend, How to do thtat ?
my React code is :
import fetch from 'isomorphic-fetch';
export function createBio (data) {
console.log(data);
return fetch('http://localhost:3001/user/create', {
method: 'POST',
mode: 'no-cors',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
}
}).then(res => {
return res;
}).catch(err => console.log(err));
}
My NodeJs code
router.post('/create', (req,res,) => {
var user = new User({title: req.params.title || "Untitled Note", body: req.params.body});
user.save();
});
How to retrieve data

req.param() searches the url path, body, and query string of the request (in that order) for the specified parameter. If no parameter value exists anywhere in the request with the given name, it returns undefined, or the optional defaultValue if specified.
url path parameters (req.params)
e.g. a request /create/4 to route /create/:id has url path params req.params.id
:id this id you can change anything you want, but you should add ":" before your parameter
body parameters (req.body)
e.g. a request with a parseable body (e.g. JSON, url-encoded, or XML) has body parameters equal to its parsed value
if you want to get the title, you can write req.body.title
For your case, I recommend you use req.body
Your back-end API
//http://localhost:3001/user/create
router.post('/create', (req,res) => {
const user = new User(
{
title: req.body.title ===null ? 'Untitled Note' : req.body.title,
text: req.body.text
});
user.save();
});
You should determine what value your data include
data = {
title: '?',
text: '?'
};
Your Fetch
import fetch from 'isomorphic-fetch';
export function createBio (data) {
console.log(data);
fetch('http://localhost:3001/user/create', {
method: 'POST',
mode: 'no-cors',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
}
}).then(res => {
return res;
}).catch(err => console.log(err));
}
Make sure of your path is right
Any way, I use 'axios' to retrieve data
router.post('/'),
(req, res) => {
const newPost = new Post({
eventTitle: req.body.eventTitle,
eventText: req.body.eventText
});
newPost.save().then(post => res.json(post));
});
axios
const postData = {
title: '?',
text: '?'
};
axios
.post('/api/posts', postData)
.then(res => console.log(res))
.catch(err => console.log(err));
Get params
**!But this title should be assigned a value. not a null value**
router.post('/:title'),
(req, res) => {
const newPost = new Post({
eventTitle: req.params.title,
eventText: req.body.eventText
});
newPost.save().then(post => res.json(post));});
const postData = {
title: '?',
text: '?'
};
axios
.post(`/api/posts/${postData.title}`, postData.text)
.then(res => console.log(res))
.catch(err => console.log(err));
If you have any questions about fetch, you can use this https://developer.mozilla.org/en-US/.
I hope this is useful for you. Actually, I never used fetch, but axios is same with it.
PS: you should add this for your server.js to get value from the client side.
Node.js body parsing middleware. Parse incoming request bodies in a
middleware before your handlers, available under the req.body
property.
const bodyParser = require('body-parser');
// for parsing application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// for parsing application/json
app.use(bodyParser.json());
Last answer for your comment and your issue.
First, you should add proxy to your client side package.json
You cannpm I concurrently to run your server and client simultaneously
Your package.json should include --- I did't create a server json, this may a wrong format. But just a test. The part of ** should be written in the server package.json file! If you don't want to use it, you can just focus on the code, it will fix your problem.
{
"name": "react",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"body-parser": "^1.18.3",
"concurrently": "^4.0.1",
"express": "^4.16.4",
"fetch": "^1.1.0",
"node-fetch": "^2.2.0",
"react": "^16.4.2",
"react-dom": "^16.4.2",
"react-scripts": "1.1.4",
"isomorphic-fetch": "^2.2.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
**"server": "node server.js",**
**"client": "npm start",**
**"dev": "concurrently \"npm run server\" \"npm run client\"",**
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:5000"
}
npm I node-fetch at client side
import React, {Component} from 'react';
//import axios from 'axios';
//import fetch from 'node-fetch';
import fetch from 'isomorphic-fetch';
class SendMessage extends Component {
constructor(props) {
super(props);
this.state = {
title: '',
text: ''
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit(e){
e.preventDefault();
const newUser = {
title: this.state.title,
text: this.state.text,
};
// axios.post('/users/create', newUser)
// .then(res => console.log(res))
// .catch(err => console.log(err));
fetch('/users/create', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(newUser)
}).then(res=>res.json())
.then(res => console.log(res));
}
onChange(e){
this.setState({[e.target.name]:e.target.value})
}
render() {
return (
<div>
<form onSubmit={this.onSubmit}>
<input type="text" name='title' onChange={this.onChange} value={this.state.title} placeholder="title"/>
<input type="text" name='text' onChange={this.onChange} value={this.state.text} placeholder="text"/>
<input type="submit" value="Submit"/>
</form>
</div>
);
}
}
export default SendMessage;
Server side server.js
const express = require ('express');
const bodyParser = require('body-parser');
//import route
const users = require('./route');
var app = express();
//Body parser middleware
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
// Use routes
app.use('/users', users);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server running on port ${port}`));
Server side route.js
const express = require('express');
const router = express.Router();
router.post('/create', (req,res) => {
console.log(req.body);
const user =
{
title: req.body.title ===null ? 'Untitled Note' : req.body.title,
text: req.body.text
};
res.status(200).json(user);
});
module.exports = router;

You're sending a request to '/user/create' when your Node.js server is listening on 'create'. Try changing
fetch('http://localhost:3001/user/create'
to
fetch('http://localhost:3001/create'

My best way, start create file api.js
import axios from "axios";
export default {
user: {
createBio: data => axios.post(`${process.env.API_HOST}/user/create`, {data}).then(res => res),
}
}
and then you can call function createBio from your component or action if you use redux,
if you get problem Access-Control-Allow-Origin use CORS

You can use body-parser middleware to parse the body of your request
in your server.js:
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json({limit: '10mb'}));
and supposing you send an object to the server like:
let data = {
myProp: 'myVal1'
}
You can then get it in the request:
router.post('/create', (req,res,) => {
let value = req.body.myProp;
console.log('value in body: ' + value);
// execute...
});
This will log:
value in body: myVal1
I would also strongly recommend using Axios for your requests instead of fetch, and read my answer in this post where I discuss some differences and how to implement axios if you are using fetch already. This way you don't need to stringify your data for example, and you solve other issues discussed there.
If you use Axios (with async/await), set your request object like so:
let reqObj = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8'
},
url: 'http://localhost:3001/user/create',
data: {
myProp: 'myVal1'
}
};
And send the request to axios with:
let response = await axios(reqObj);

Related

i try to upload file in my mocha nodejs test but i got [Object null prototype] { file: { ... }}

i find evrywhere solution white :
app.use(bodyParser.urlencoded({extended: true}));
i can use
JSON.stringify(req.files)
but im sur having a way to fix my problem
my mocha test :
it('a file', async function () {
const body = { pseudo: 'user', password: 'test#123', mail: 'supermail' };
const response = await fetch(hostName + '/authentication/register', {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' }
})
const usr = await response.json();
request.post('/usrAction1/doc')
.field('token', usr.token)
.attach('file', 'test/test.pdf')
.end(function (err, res) {
if (err) {
console.log(err)
}
console.log(res.status) // 'success' status
});
});
and my rout handler :
router.post('/doc', async (req, res) => {
console.log('req.files');
console.log(req.files)
})
also my server.js:
import express from 'express'
import authentication from './src/login.js'
import './global/host.js'
import bodyParser from 'body-parser'
import cors from "cors"
import verifyToken from './middleware/auth.js'
import { userAction1, userAction2 } from './src/userAction.js'
import verifyLevel from './middleware/level.js'
import fileUpload from 'express-fileupload';
export default function myApp() {
const whitelist = [/http:\/\/localhost:*/, /http:\/\/127.0.0.1:*/]
const corsConfig = { origin: whitelist }
const app = express();
const port = hostPort;
//json encoded
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
app.use(cors(corsConfig))
// enable files upload
app.use(fileUpload({
createParentPath: true
}));
app.use('/usrAction1', userAction1())
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
return app;
}
myApp();
but don't to work for me .
i also test white external client server who juste runing a form and send it to my tested adress and
do the same [Object null prototype]
thank u for evry litel help
i waiting of some help i using this magique code i found somwhere on stackoverflow:
req.files && Object.keys(req.files)?.map((obj, idx) => { console.log(req.files['file'].data) })
if somone have a better idea i waiting .
thank to all

Send data between GraphQL Node.js server and React in Nx

I setup two projects, Node.js and React in Nx monorepo. I would like to use GraphQL for communication. Projects I'm running with command nx serve api(Node.js) and nx serve totodile (React). Problem is that React cannot access data from /graphql endpoint.
React is running on http://localhost:4200/.
Node.js is running on http://localhost:3333/.
Node.js part
According to GraphQL instructions for Node.js I run Node.js server. I have created two endpoints /api and /graphql.
import * as express from 'express';
import { graphqlHTTP } from 'express-graphql';
import { Message } from '#totodile/api-interfaces';
import { buildSchema } from 'graphql';
const app = express();
const greeting: Message = { message: 'Welcome to api!' };
app.get('/api', (req, res) => {
res.send(greeting);
});
app.use('/graphql', graphqlHTTP({
schema: buildSchema(`
type Query {
hello : String
}
`),
rootValue: {
hello: () => 'Hello world'
},
graphiql: true,
}));
const port = process.env.port || 3333;
const server = app.listen(port, () => {
console.log('Listening at http://localhost:' + port + '/api');
});
server.on('error', console.error);
In a result I am able to connect to http://localhost:3333/graphql and receive response. So graphql server is working well.
// graphql response
{
"data": {
"hello": "Hello world"
}
}
React part
Inside functional component I fetch with /api and /graphql. First one return valid data, but /graphql is returning 404, Cannot POST /graphql.
useEffect(() => {
fetch('/api') // successfully return data
.then((r) => r.json())
.then(setMessage);
fetch('/graphql', { // 404, no data
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({query: "{ hello }"})
})
.then(r => r.json())
.then(data => console.log('data returned:', data));
}, []);
I investigate that:
http://localhost:4200/api return valid data ("message": "Welcome to api!")
http://localhost:3333/api return valid data ("message": "Welcome to api!")
http://localhost:4200/graphql 404 no data
http://localhost:3333/graphql return valid data ("hello": "Hello world")
It must be something with ports.
I don't understand how /api is able to return any data. Why on both ports?
What should I do to share data from /graphql to react?
To fix issue there was 2 steps to do:
In React I should fetch from endpoint with port fetch('http://localhost:3333/graphql',(...))
In Node.js there is need to use cors library
import express from "express";
import cors from 'cors';
const app = express();
app.use(cors());
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
...

Fetch call returns react index.html and chrome gives error Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

I am trying to fetch data from my local express server, and display it with react, but it seems that the index.html of the react app is being returned. If I check the network tab in the console and it shows that there is a fetch request with the name "projects/" and when I hover over it it shows "http://localhost:3000/api/projects". The console indicates that the problem is in line 13 of the react file which is "fetch('/api/projects/')". I've been trying for a while to fix this but can't seem to get it right. Code below
Express:
const express = require("express");
const app = express();
app.use(express.json());
let projects = [
{
id: 1,
title: "project1",
description: "One - description",
url: "www.One.com"
},
{
id: 2,
title: "project2",
description: "Two - description",
url: "www.Two.com"
},
{
id: 3,
title: "project3",
description: "Three - description",
url: "www.Three.com"
}
];
app.get("/api/projects", (req, res) => {
res.json(projects);
});
const PORT = 5000;
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
React:
import React from "react";
import "./App.css";
class App extends React.Component {
constructor() {
super();
this.state = {
projects: []
};
}
componentDidMount() {
fetch("/api/projects/")
.then(res => res.json())
.then(projects =>
this.setState({ projects }, () =>
console.log("Projects fetched...", projects)
)
);
}
render() {
return (
<div className="App">
<h1>Projects</h1>
</div>
);
}
}
export default App;
React package.json:
{
"name": "my-full-stack-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:5000",
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [">0.2%", "not dead", "not op_mini all"],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Your server is running on port 5000 and the client on port 3000. So, you have to call the api request as
fetch('http://localhost:5000/api/projects/')
If you don't specify the full URL, the request will be sent to http://localhost:3000/api/projects
You can also store the base URL in a constant.
import React from 'react';
import './App.css';
const baseUrl = 'http://localhost:5000';
class App extends React.Component {
constructor() {
super();
this.state = {
projects: []
}
}
componentDidMount() {
fetch(`${baseUrl}/api/projects/`)
.then(res => res.json())
.then(projects => this.setState({ projects }, () => console.log('Projects fetched...', projects)));
}
render() {
return (
<div className="App">
<h1>Projects</h1>
</div>
);
}
}
export default App;
Seems it was a cross-origin request. I installed the cors middleware, following the steps in the expressjs documentation, and added it to my express file and used app.use(cors()). Everything works now!
Just throwing this in, I know this has been answered, but I encountered this problem and was spinning my wheels for a while on it, despite all the solutions. Here is how I figured out to make it work:
I was a bit confused about the ports to use, as the app opens in port 3000, even though I had specified 5000 for my Express server. So I changed all ports everywhere to 3000 to try it out.
then I restarted my server first, then my react app, and it asked me if I wanted to open it on another port because 3000 was already being used. I said yes, and viola, it works. It now opens on port 3001 and everything works beautifully.
Code below to help any who may come to this page later, like I did.
server.js (express):
const express = require('express');
const cors = require('cors');
const knex = require('knex');
const db = knex({
client: 'pg',
connection: {
host: "127.0.0.1",
user: "",
password: "",
database: "",
},
});
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
// CORS implemented so that we don't get errors when trying to access the server from a different server location
app.use(cors());
// GET: Fetch all movies from the database
app.get('/', (req, res) => {
db.select('*')
.from('cards')
.then((data) => {
console.log(data);
res.json(data);
})
.catch((err) => {
console.log(err);
});
});
const port = 3000;
app.listen(port, () => console.log(`Server running on port ${port}, http://localhost:${port}`));
React App.js:
import React, { useState, useEffect } from 'react';
import './App.css';
const App = () => {
useEffect(() => {
const getAPI = () => {
const API = 'http://127.0.0.1:3000';
fetch(API)
.then((response) => {
console.log(response);
return response.json();
})
.then((data) => {
console.log(data);
setLoading(false);
setApiData(data);
});
};
getAPI();
}, []);
const [apiData, setApiData] = useState([]);
const [loading, setLoading] = useState(true);
return (
..... react stuff here .....
);
};
export default App;

I'm getting a "githubClientID" is not defined when calling the "config" package using the GitHub API

I'm creating a feature that to retrieves GitHub user names via the GitHub API.
When sending the GET request from Postman, I got a server error that reads:
"Configuration property "githubClientId" is not defined"
Despite the fact that I called the config package with githubClientID defined in config/default.json, like this:
{
"mongoURI": "mongodb+srv://massas:oir#socialapp-2dg3r.mongodb.net/test?retryWrites=true&w=majority",
"jwtToken" : "oecret",
"githubClientId:": "ID",
"githubSecret": "SECRET"
}
// change the values for public viewing
Here's the code that's calling the API:
const express = require('express');
const request = require('request');
const config = require('config');
// #route GET api/profile/github/:username
// #desc Get user repos from username
// #acess Private
router.get('/github/:username', (req, res) => {
try {
const options = {
uri: `https://api.github.com/users/${
req.params.username
}/repos?per_page=5&sort=created:asc&client_id=${config.get(
'githubClientId'
)}&client_secret=${config.get('githubSecret')}`,
method: 'GET',
headers: {
'user-agent': 'node.js'
}
};
request(options, (error, response, body) => {
if (error) console.error(error);
if (response.statusCode !== 200) {
return res.status(404).json({
msg: 'No Github profile found'
});
}
res.json(JSON.parse(body));
});
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
How can I resolve this error?
1- You need to change the options object from:
const options = {
uri: `https://api.github.com/users/${
req.params.username
}/repos?per_page=5&sort=created:asc&client_id=${config.get(
'githubClientId'
)}&client_secret=${config.get('githubSecret')}`,
method: 'GET',
headers: {
'user-agent': 'node.js'
}
};
to:
const uri = encodeURI(
`https://api.github.com/users/${req.params.username}/repos?per_page=5&sort=created:asc`
);
const headers = {
'user-agent': 'node.js',
Authorization: `token ${config.get('githubToken')}`
};
const gitHubResponse = await axios.get(uri, { headers });
2- Make sure to add a default.json file in config folder with your GitHub secret access token
{ "githubToken": "<yoursecrectaccesstoken>" }
3- Install axios in the root of the project, if you didn't install it
npm i axios

GraphQL API works with Postman, but failed with Javascript fetch

I built a GraphQL server as follows,
import express from 'express';
import graphqlHTTP from 'express-graphql';
import { schema } from './data/schema';
const app = express();
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res) {
res.sendFile('index.html');
});
app.use('/graphql', graphqlHTTP({
schema: schema,
graphiql: true
}));
app.listen(8081, () => {
console.log('Running server on port localhost:8081/graphql');
});
And I can make a POST call from Postman like below,
However, when I try to call the API with fetch in the app.js file which is loaded in the index.html as follows,
function fetchQuery(query) {
return fetch('/graphql', {
method: 'POST',
header: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ query })
}).then(response => {
return response.json();
});
}
const query = `{
friend {
firstName
}
}`;
fetchQuery(query).then((data) => {
console.log(data);
});
It says the following errors,
app.js:2 POST http://localhost:8081/graphql 400 (Bad Request)
and response error message: "Must provide query string."
Headers should be passed in by providing a headers property in the options object, not header.
headers: {
'Content-Type': 'application/json',
},
The content type for the request is necessary for body-parser to know how to correctly parse the body. Without the header, body ends up an empty object and therefore req.body.query is undefined, which is why you see that error.

Categories