How to send data from react.js to node? - node.js

I am a beginner in web devolopment and I'm developing an application using react and nodejs. I've been looking for ways to send the data from front end i.e, react(data received from the user) to nodejs code so that I can process it and send it back to the UI. I saw some resources mentioning that I can use fetch and axios but I can't quite follow it. So basically my application is about executing the pipe commands of linux. There will be few buttons to choose which command to execute(Like sort, uniq etc). There will be a text area to get the input text and a label to display the output. So how can I send the input data to the nodejs function so that I can process it with some built-in modules and return the output to the label.My code for text area looks like this
import { useState } from "react";
const Text_area = () =>{
const[text,setText] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
const data = {text};
}
return(
<>
<form onSubmit={handleSubmit}>
<label>Input here</label>
<textarea value= {text} required onChange={(e)=>setText(e.target.value)}/>
<button>OK</button>
</form>
</>
);
}
Share your thoughts please!

I assume you have only index route, that's why fetch is pointing to index.
const[text,setText] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
const newText= { text };
fetch("/", {
method: "POST",
headers: {"Content-Type": "application/JSON"},
body: JSON.stringify(newText)
})
}
Above, fetch method is used to send your data to relevant route in your node.js file.
And in your server.js file, you can code something like this to see if it works:
app.post("/", function(req, res){
res.send(req.body);
});
Please let me know if it works for you.

Think of your problem like a Form HTML element. How can a form send data to server?
Basically, they use HTTP GET/POST method. If you don't know it, Google! But for now, let just understand that: To send data from react.js to node, you need do something with HTTP GET/POST method.
<form action="/send_form" method="post">
<input type="text" id="fname" name="fname">
<input type="text" id="lname" name="lname">
<input type="submit" value="Submit">
</form>
form element has done it for you. This is why you see people mentioned axios because what if I don't use form? How can I do the same thing without form?
Then how do server receive information? You will do that by code something in Node.js. Googled yourself :>.
Then people mentioned Express.js. Think of it as "React" of Node.js, which mean it's a framework. You don't need to know "Express.js" to receive information sent from React.

Related

Is there a way to upload a file to Node.js using React and Observables (rx.js)?

I have a MERN stack web app that makes heavy use of rx.js "Observables". I have been searching for docs, plugins, npm modules, etc. that enable my app to do an image file upload (binary file) to a Node.js api endpoint (endpoint utilizes the npm module "multer" on the receiving end).
I have been unable to find tutorials, libraries or modules that support this specific functionality using the MERN + Observables stack. Google returns examples for Angular only. And there appears to be no relevant questions of this type on stackoverflow.
I have a complex form, some fields are required, and some are optional content. One piece of required input is an image file for upload. My aim/hope is to deliver all this data to the server using a chained series of Observables.
Is there a react plugin/module/library similar to axios that uses observables, or am I just guilty of "wishful thinking"? I am wondering if this is possible, and if anyone can point me towards a tutorial, article, example, github, etc., or just straight up show me the way.
Note: I don't have a problem with implementing a special one-off case and using a library like axios, or even just writing raw JS XHR to get it done, just thought it would be nice, clean, and homogenous to also accomplish this task with observables... also, I am fairly new to observables, so it's possible I could be missing something important or simply not know that this kind of functionality is not supported with this library (rx.js).
Any help, advice, or insight would be useful! Links to docs/articles/tutorials are greatly appreciated! Thanks in advance!
You can supply FormData instance as rxjs.ajax body parameter, and browser will automatically set proper Content-Type header.
See example code:
const { ajax } = rxjs.ajax; // = require("rxjs/ajax")
const { fromEvent } = rxjs; // = require("rxjs")
const { mergeMap } = rxjs.operators; // = require("rxjs/operators")
const fileInput = document.getElementById("file");
const res$ = fromEvent(fileInput, "change").pipe(
mergeMap(e => {
const { files } = e.target;
const body = new FormData();
body.append("some-field", "fome-field-value");
body.append("file", files[0]);
return ajax({
url: 'https://httpbin.org/post',
method: 'POST',
body
});
})
);
const htmlSubscription = res$
.subscribe(e => {
const response = JSON.stringify(e.response, null, 2);
document.getElementById('root').innerHTML = `
<div>
<span><b>POST</b> https://httpbin.org/post</span>
<pre>${response}</pre>
</div>`;
});
<script src="https://unpkg.com/rxjs#6.5.3/bundles/rxjs.umd.min.js"></script>
<input type="file" id="file" />
<div id="root">select file and see what happens...</div>
Also take a look:
for more info regarding ajax, here is detailed answer
there is also fromFetch operator, using it you can wrap fetch request with multipart/form-data

Why is my image file being converted to a string?

Edit, original question has been resolved as to why file was converted to string. The code has been edited to reflect these corrections. The API handler is now outputting object as data type and buffer as the value of request.payload.file.
I'm using Aurelia to make a Single Page App. There is a HTML form that accepts two input fields, one for a file, one for text. These fields are bound to variables (selecetdImage and title) in an associated TypeScript view model. In the viewmodel they are used as arguments in a function that appends them to formData and sends a http post request with the formData to an Node/js Hapi framework API handler.
When I console.log(typeof(selectedImage) in the Aurelia app, it states object, but when I console log typeOf(selecetdImage) in the handler, I get String. I'm guessing this is why my function isn't working and giving 500 error messages
The handler itself works. I used it in a MVC server based web app. In that context, HTML form triggers a post request, and the MVC handler successfully receives the file, writes it to local/temp.img and uploads it to cloudinary.
But with the API version, where I assembled the form data myself as above, the file isn't written to local/temp.img and the cloudinary upload fails.
Edit.
I changed the viewmodel variables to
title = null;
files = null;
and I changed the formData append function to:
formData.append('file', File, files[0]);
As per the example here. The code below is now modified to match this update.
Now when I console log the value of file in the API handler, the output is:
<Buffer ff d8 ff e0 00 10.......
I'm not sure what to do with this data. I assume it's the image binary data in octal? And if so, does anyone know how to write it as an image in node?
The payload is no longer of type string, now it's type object.
<form submit.delegate="uploadPhoto()" enctype="multipart/form-data">
<div class="two fields">
<div class="field">
<label>File</label>
<input type="file" name="file" accept="image/png, image/jpeg" files.bind="files">
</div>
<div class="field">
<label>Title</label> <input value.bind="title">
</div>
</div>
<button type="submit"> Upload </button>
</form>
//photoUpload.ts// (view model associated with above html
#inject(POIService)
export class PhotoForm {
#bindable
photos: Photo[];
title = null;
files = null;
constructor (private poi: POIService) {}
uploadPhoto() {
const result = this.poi.uploadPhoto(this.title, this.files);
console.log(this.title);
console.log(result);
}
//POIService (where contains injected function to create HTTP request
async uploadPhoto(title: string, files){
console.log("now uploading photo for: " + this.currentLocation)
let formData = new FormData();
formData.append("title", title);
formData.append("location", this.currentLocation); //don't worry about this variable, it's set by another function every time a page is viewed
formData.append("file", files[0]);
const response = await this.httpClient.post('/api/locations/' + this.currentLocation + '/photos', formData);
console.log(response);
}
//API Handler (accepts HTTP request, writes the image to a local folder, the uploads to cloudinary and returns the url and photo_id which are stored in a Mongod document
create: {
auth: false,
handler: async function(request, h) {
const photo = request.payload.file;
await writeFile('./public/temp.img', photo);
const result = await cloudinary.v2.uploader.upload('./public/temp.img', function(error, result) {
console.log(result)
});
const newPhoto = new Photo({
title: request.payload.title,
url: result.url,
public_id: result.public_id,
location: request.params.name
})
await newPhoto.save();
return newPhoto;
}
},
Is it a very long string, containing "data:b64" in the first 15 or so characters? If so, that means it's the base64 data.

redirect post request from post request

trying to send post form request to another server.
I'm getting post request from my localhost lets say on POST /deposit
and I want later to redirect user to payment website with some kind of this data
​form to which I want user to redirect after he posts to: localhost:3000/deposit
<form action='http://testpayment.com/pay' class='redirect_form' method='post'>
<input type='hidden' name='key' value='${data.api_id}'>
<input type='hidden' name='signature' value='${data.api_secret_key}'>
<input type="hidden" name='user_id' value='${data.user_id}'>
<input type="hidden" name="payment_method" value="master_card">
<input type="hidden" name="customproduct" value='[{
"productId":"deposit-${currencyPayway.currency.code}",
"productName":"Test Product",
"productType":"fixedProduct",
"currency":"${currencyPayway.currency.code}",
"amount":${amount}}]'>
<button type='submit'>Pay</button>
</form>
Post route:​
app.post('/deposit', function(req, res) {
// some logic applies here
//redirect part ???
});
Any ideas how to do it?
Thanks.
UPDATE:
Use case of what I'm ting to do:
Lets say we have multiply payment providers. On deposit action in any way after applying some logic we need to redirect user to payment provider website for card/account details input after which user will be redirect to my website back again by payment provider. Now front writes custom logic for all deposit methods each time. But I tries to decouple front from that stuff and handle it completely on backend and unify deposit process.
In most cases as I know, paymant gateway works like this:
you will create a form and as an URL you put your Payment Provider URL https://secure.paymentprovider.com/deposit
you will create a form get the data from user, send on server side to Payment Provider, as a return you should get a SessionId, some kind of unique key and then you redirect user but with a GET method to Payment Provivder url ie. https://secure.paymentprovider.com/deposit/{token/sessionId}
Here is an example PayU - http://developers.payulatam.com/en/web_checkout/
Maybe you can attach link to Payment Provider api?
use stream.pipe
https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options
app.post('/', (req, res,next) => {
var request = require('request');
var pipe = req.pipe(request.post('localhost:3000/deposit'));
var response = [];
pipe.on('data',function(chunk) {
response.push(chunk);
});
pipe.on('end',function() {
var res2 = Buffer.concat(response);
console.log(res2);
res.send(res2)
});
})

"Waiting for localhost" after form submission: node/express/react

I am working with node/express/react. I am using a form on the frontend to delete entries from the backend database:
<form id="delete" action="/delete" method="POST">
<p>First name:</p>
<input type="text" name="first" />
<p>Last Name:</p>
<input type="text" name="last" />
<input type="submit" value="delete person from database" />
</form>
The entry gets deleted from the backend database. But I get this message at the bottom of the browser window on the frontend:
Waiting for localhost...
Then after about a minute, I get this:
"This page isn’t working
localhost didn’t send any data.
ERR_EMPTY_RESPONSE"
Here is the relevant express endpoint:
app.post('/delete', function(req, res) {
var first = req.body.first;
var last = req.body.last;
db.collection("employees").remove({first:first, last:last}, function(error, response) {
if (error) throw error;
console.log("success");
});
});
If I do send data via res.send() or res.json(), then the entire front-end web page gets erased and replaced with whatever data was sent from the backend.
Often with form submission, you send the user to a different web page after submit. But in my case, I want the user to stay on the same page without reloading the page.
How do I get the error messages to go away in this case?
For the node/express part of the question, "How do I get the error messages to go away in this case?", you have to send some sort of response from the endpoint:
app.post('/delete', function(req, res) {
var first = req.body.first;
var last = req.body.last;
db.collection("employees").remove({first:first, last:last}, function(error, response) {
if (error) throw error;
console.log("success");
res.status(200).send({msg: `Deleted ${first} ${last}, RIP`}); //returning a status object, but you could return anything useful to the client code here.
});
});
This gets rid of the error, but you would still be redirected to a page showing the JSON output from the API.
Staying on the same page after submitting a form is discussed here and many other posts as well. You mention it is a React app--you might want to use that framework for making API calls from your frontend.

backbone model.save() does not set the response body of the express server with body parser

I am trying to save (post) a Backbone model using a model.save().
Model:
Backbone.Model.extend({
urlRoot: '/project/',
defaults: {
projectname: "default projectname"
}
});
Saving the model (in my Backbone.router object):
putTest: function(id) {
var projectItem = new ProjectModel({projectname: "This shiny new project"});
projectItem.save();
},
I would expect my node/express router on the server, which uses the middleware 'body-parser', to get the attributes of the model on the express request.body object, like so:
post: function(request, response) {
console.log(request.body.projectname);
}
but the response.body object is empty.
When I am using a regular html form with method="post" like so:
<form id = "createProject"
action = "/project/"
method = "post" >
<input type="text" name="projectName" value="Project name" />
</form>
everything is working as expected.
I have struggled with this the whole day now, and can't see what I am doing wrong.
Have I misunderstood the whole Backbone.model.save() concept or is there an other object on the express request object that holds the attributes of my Backbone model when saving?
By default, an HTML <form> sends application/x-www-form-urlencoded data and no JSON like Backbone.sync() does (that's used by .save() internally).
Open your browser's developer tools and take a look in the network analysis when saving the model to make sure the request works correctly (JSON Body, URL, ...).
However, since your backend handles form data correctly, I'd guess your middleware is not configured in the way you want it to.

Resources