Passing data from my NodeJS back to React component - node.js

I have a React component which is GaleryPage and i want to show a list of information i found them with my Back end side which are file_name and Type_contract .This is my back End side code :
app.post('/convert', upload.single('file'),(req, res) =>{
if(req.file){
let file= req.file.filename
let Type_contract = 'Contract'
let file_name = path.basename(file,path.extname(file))
console.log(file_name);
console.log(Type_contract);
}
res.redirect('/');
and here is my React component :
import React, { Component } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
class GaleryPage extends Component {
constructor(props) {
super(props);
this.state = {
file_name: '',
Type_contract:''
};
}
componentDidMount() {
const data = new FormData();
fetch('http://localhost:8080/upload',{
method: 'POST',
body: data
})
.then((file_name,Type_contract) => this.setState({
file_name: file_name,
Type_contract:Type_contract
})
)}
render() {
return (
<div>
<ul>
<li file_name={this.state.file_name}>file_name=
{this.state.file_name}</li>
<li Type_contract={this.state.Type_contract}>Type_contract=
{this.state.Type_contract}</li>
</ul>
</div>
);
}
}
export default GaleryPage;
when i try this code i find always empty page and no data is not showning

Related

React js how to set and get parameter from another file?

i'm new in react, and i would like to ask about how to send parameter to another function in class component. For example :
Main.js
import React, { Component } from "react";
import Form from "./Form";
import fetchData from "./Action";
export default class Main extends Component {
constructor(props) {
super(props);
this.fetchingData = this.fetchingData.bind(this);
this.state = {
list: 0
};
}
fetchingData(x) {
const data = fetchData(); // => from Action.js (get the return)
this.setState({ list: data });
}
componentDidMount(){
this.fetchingData();
}
render() {
return (
<>
<h3>Data</h3>
<Form />
<p>result: {this.state.list}</p> //=>show the result and auto update when click by button
</>
);
}
}
Form.js
import React from "react";
import fetchData from "./Action";
function Form() {
const handlerClick = (v) => {
fetchData(v); //=>set value form this function (from action.js)
};
return (
<>
<button onClick={(e) => handlerClick(1)}>Push</button>
</>
);
}
export default Form;
Action.js
const fetchData = (v) => {
return v;
};
export default fetchData;
From that code i would like to send parameter from button handlerClick() inside of that function, there is fetchData(), this function will keep the param and return it to the Main.js for fillup the setState. And the result will auto updated, when click the button Push.
Would u like to help me fixing my code ?
You have to send the function fetchingData as a prop to Form, something like: <Form fetchingData={fetchingData} /> from Main.js, that way you can call the function from <Form /> component and have your value saved.
Main.js
import React, { Component } from "react";
import Form from "./Form";
import fetchData from "./Action";
export default class App extends Component {
constructor(props) {
super(props);
this.fetchingData = this.fetchingData.bind(this);
this.state = {
list: 0
};
}
fetchingData(x) {
const data = fetchData(x); // => from Action.js (get the return)
this.setState({ list: data });
}
componentDidMount() {
this.fetchingData();
}
render() {
return (
<>
<h3>Data</h3>
<Form fData={this.fetchingData} />
<p>result: {this.state.list}</p>
</>
);
}
}
Form.js
import React from "react";
import fetchData from "./Action";
const Form = (props) => {
const handlerClick = (v) => {
if (props.fData) {
props.fData(v);
} else {
fetchData(v); //=>set value form this function (from action.js)
}
};
return (
<>
<button onClick={(e) => handlerClick(10)}>Push</button>
</>
);
};
export default Form;
Action.js
const fetchData = (v) => {
return v;
};
export default fetchData;
Live Demo

Cannot add to cart on frontend react.js, although the end points are working correctly and it is adding items to cart in post man app

so I am trying to add to cart. My node.js endpoints are working correctly and I am able to add items to cart when viewed in postman app but it does not display items on the front end, and when inspecting through the chrome developers tools, the items array is empty when on the postman while testing it is successfully storing items.
Here is my server.js
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const cors = require("cors");
const mongoose = require("mongoose");
let Book = require("./models/bookModel");
const port = 4000;
app.use(cors());
app.use(bodyParser.json());
mongoose.connect("mongodb://127.0.0.1:27017/books", { useNewUrlParser: true });
const connection = mongoose.connection;
connection.once("open", function() {
console.log("MongoDB database connection established successfully..");
});
const bookRoutes = express.Router();
app.use("/books", bookRoutes);
const cartRoutes = express.Router();
app.use("/cart", cartRoutes);
bookRoutes.route("/").get(function(req, res) {
Book.find(function(err, books) {
if (err) {
console.log(err);
} else {
res.json(books);
}
});
});
bookRoutes.route("/:id").get(function(req, res) {
let id = req.params.id;
Book.findById(id, function(err, book) {
res.json(book);
});
});
cartRoutes.route("/").get(function(req, res) {
var cart = req.session.cart;
var displayCart = { items: [], total: 0 };
var total = 0;
for (var item in cart) {
displayCart.items.push(cart[item]);
total += cart[item].qty * cart[item].price;
}
displayCart.total = total;
return res.json(displayCart);
});
cartRoutes.route("/:id").post(function(req, res) {
req.session.cart = req.session.cart || {};
var cart = req.session.cart;
let id = req.params.id;
Book.findById(id, function(err, book) {
if (err) {
console.log(err);
}
if (cart[id]) {
cart[id].qty++;
} else {
cart[id] = {
item: book._id,
title: book.title,
price: book.price,
qty: 1
};
}
res.redirect("/cart");
});
});
app.listen(port, function() {
console.log("Server is running on Port: " + port);
});
the server response:
{
"items": [
{
"item": "5dd7668f33c21d811b74f403",
"title": "Modern PHP",
"price": 25.65,
"qty": 1
},
{
"item": "5dd6bb36725bbba1ca482eea",
"title": "Professional Node.js",
"price": 20.56,
"qty": 2
}
],
"total": 66.77
}
cart.js
import React, { Component } from "react";
import axios from "axios";
import CartItem from "./cart1-item.component.js";
import "bootstrap/dist/css/bootstrap.min.css";
import { throws } from "assert";
export default class Cart extends Component {
constructor(props) {
super(props);
this.state = {
items: []
};
}
componentDidMount() {
axios
.get("http://localhost:4000/cart/")
.then(response => {
this.setState({
items: response.data.items
});
console.log(response.data.items);
})
.catch(function(err) {
console.log(err);
});
}
checkItems() {
return this.state.items.map((currItem, i) => {
return <CartItem book={currItem} key={i}></CartItem>;
});
}
Calculate = item => {
return item.qty * item.price;
};
render() {
return (
<div className="container">
<div className="row">{this.checkItems()}</div>
</div>
);
}
}
cartitem.js
import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
const CartItem = props => {
return (
<div className="container">
<h2>{props.book.title}</h2>
</div>
);
};
export default CartItem;
here is the app.js code for cart route
<Route path="/cart" exact component={Cart}></Route>
Edited code book-details.component.js
import React, { Component } from "react";
import "../css/styles.css";
import axios from "axios";
export default class BookDetails extends Component {
constructor(props) {
super(props);
this.state = {
book: []
};
}
componentDidMount() {
axios
.get("http://localhost:4000/books/" + this.props.match.params.id)
.then(response => {
this.setState({ book: response.data });
})
.catch(function(err) {
console.log(err);
});
}
AddToCart = e => {
let id = e.currentTarget.getAttribute("id");
axios.post(`http://localhost:4000/cart/${id}`).then(() => {
window.location.href = "http://localhost:3000/cart/";
});
};
render() {
const { book, quantity } = this.state;
return (
<div className="container">
<div className="row">
<div className="col sm-4">
<img src={`./images/${book.cover}`}></img>
</div>
<div className="col sm-8">
<h2>{book.title}</h2>
<ul>
<li>Category: {book.category}</li>
<li>Author: {book.author}</li>
</ul>
<p className="button blue">${book.price}</p>
<p>{book.description}</p>
<button id={book._id} onClick={this.AddToCart}>
Add To Cart
</button>
</div>
</div>
</div>
);
}
}
App.js
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import BooksList from "./components/book-list.component.js";
import BookDetails from "./components/book-details.component.js";
import "bootstrap/dist/css/bootstrap.min.css";
import Navigation from "./components/navigation.component";
import Cart from "./components/cart1.component";
class App extends Component {
render() {
return (
<Router>
<Navigation></Navigation>
<Route
path="/"
exact
render={() => (
<div className="container">
<BooksList></BooksList>
</div>
)}
></Route>
<Route path="/books/:id" exact component={BookDetails}></Route>
<Route path="/cart/" exact component={Cart}></Route>
</Router>
);
}
}
export default App;
Any help would be appreciated.
i think i should point out that what you are passing to CartItem is "books" while in the CartItem component you are trying to get "items" from props (this.props.items). that part should be this.props.books.title.
UPDATE:
After you updated your question, i noticed this addition:
and on clicking the add to cart button it navigates to the link
href={"/cart"} className="button"> Add to Cart
this might be where your problem is coming from. on the API, to add books to cart, you did something like this:
cartRoutes.route("/:id").post(function(req, res) {
req.session.cart = req.session.cart || {};
var cart = req.session.cart;
let id = req.params.id;
so you are basically making a post request (even though from the code you are not really posting any data since you are just extracting the id from the url parameter. maybe you should consider making this a get request).
the key part here is the post http method and the id that is expected as the url parameter.
to make things simple on yourself, you can change your "add to cart" to something like:
<button className="button" id={book.id} onClick={this.addToCart}>
Add to Cart
</button>
for addToCart, you can do something like this:
addToCart=(e)=>{
let id = e.currentTarget.getAttribute("id");
axios.post(`http://localhost:4000/cart/${id}`)
.then(()=>{window.location.href = "http://localhost:3000/cart"})
}
note that like i said, you can replace the post request above to a get request since you are not actually posting any form data. if you wish to do this, you should also change the corresponding post request in your api to a get request.
Also, note that you can't get cart items posted through postman from the browser. you are using node sessions for cart items storage. you have to create a different react component (if you have not already created it) from where you can send the post request above to your express api

How to receive JSON Object from node and display it on client side in react?

I am sending a json object using res.json. On the client side I am trying to set the json object to a piece of state.
Ive tried to .json() the response but that still does not let me assign it.
This is the server side sending the JSON File
app.get('/api/getPlace', async (req, res) => {
const response = await client.search({
searchType: "Coffee",
location: "San Francisco, CA",
})
const foodPlace = response.jsonBody.businesses[9];
console.log(foodPlace);
res.json(foodPlace)
})
Below is the whole component file to render the json object
import React, { Component } from 'react';
import axios from 'axios';
class RandomPlace extends Component {
constructor(props) {
super(props);
this.state = {
response: {},
};
}
async componentDidMount() {
const res = axios.get('/api/getPlace');
this.setState({ response: res.data })
}
render() {
return (
<div>
{this.state.response}
</div>
);
}
}
export default RandomPlace;
The client call must be awaited:
async componentDidMount() {
const res = await axios.get('/api/getPlace');
this.setState({ response: res.data })
}
import React, { Component } from 'react';
import axios from 'axios';
class RandomPlace extends Component {
constructor(props) {
super(props);
this.state = {
response: {},
};
}
async componentDidMount() {
const res = await axios.get('/api/getPlace');
this.setState({ response: res.data })
}
render() {
return (
<div>
{this.state.response}
</div>
);
}
}
export default RandomPlace;
REST api calls are asynchronous, which means the code proceeds to the next statement without waiting for the api call to compelete. When await is adding before the call, the execution will pause till the call completes or timesout (if specified) before proceeding to the next line. async/await is a better alternative to promises.

Component are not update after redirect back from Nodejs

I've created small ReactJS app and get retrieve user feeds data from facebook api.
If data not shown, call NodeJS api and fetch feeds from facebook and redirect back to index screen. Problem is once redirect back, I found that feeds is already in database and after redirect back to index page, feeds are not shown, I need to reload browser screen.
My problem is which component should I use after redirect back to original screen in react?
import React, { Component } from 'react';
import ReloadButton from './ReloadButton';
import Feeds from './Feeds';
import Alert from './Alert';
class MyTest extends Component {
constructor(props) {
super(props);
this.state = {
feeds: []
};
}
componentDidMount() {
fetch('/fetch')
.then(response => response.json())
.then(data => this.setState({ feeds: data }));
}
render() {
const { feeds } = this.state;
return (
<div className="container-fluid">
<a className="btn btn-primary" href="/auth/facebook">Reload</a>
{ feeds.length > 0 ? <Feeds feeds={ feeds } /> : <Alert /> }
</div>
);
}
}
export default MyTest;
if I were you I did something like this. please say if it is helpful
interface ExampleProps {
someDataFacebookSendMe: any; //this prop used to get redirect from facebook and for first time is null
}
interface ExampleState {
feeds: []
spinning: boolean;
isDataCollected: boolean; // this proprty check for gotten data
}
export class Example extends React.Component<ExampleProps, ExampleState> {
constructor(props) {
super(props);
this.state = {
feeds: [],
spinning: true,
isDataCollected: false
};
}
componentDidMount() {
if (!!this.props.someDataFacebookSendMe) {
while (!this.state.isDataCollected) {
this.getData()
}
fetch('/fetch')
.then(response => response.json())
.then(data => {
if (data !== null && data !== undefined) {
this.setState({ feeds: data, spinning: false, isDataCollected: true })
}
});
}
else {
this.setState({spinning: false})
}
}
getData() {
fetch('/fetchIsDataExists') // this method check if data has gotten or not
.then(data => this.setState({isDataCollected: true }));
}
render() {
const { feeds } = this.state;
return (
<div className="container-fluid">
<Spin spinning={spinning} >
<a className="btn btn-primary" href="/auth/facebook">Reload</a>
{feeds.length > 0 ? <Feeds feeds={feeds} /> : <Alert />}
</Spin>
</div>
);
}
}

ReactJS - item doesn't append instantly only refreshing page

I'm using ReactJS, NodeJS, MongoDB.
In my project I have a Task List and I'm adding new tasks (this works!) but only appends/show that new task when I refresh the page but I'm using ReactJS so I can have a more responsive/interactive website but I'm new at this and I'm still learning and I don't know what to do...Maybe I have to make something with the state?!
Hope you can help me! Thanks!
Here's my NewTask Component:
import React, { Component } from 'react';
import './NewTask.css';
class NewTask extends Component {
constructor(props) {
super(props);
this.state = {
projectId: null,
tasktitle: '',
taskcomment: ''
};
}
postDataHandler = () => {
let data = {
tasktitle: this.state.tasktitle,
taskcomment: this.state.taskcomment
};
fetch(`/dashboard/project/${this.props.projectId}/tasks/newtask`, {
method: 'POST',
data: data,
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}).then(response => { return response.json() })
.catch(error => console.error('Error:', error));
}
render() {
return (
<div>
<input type='text' className='form-control input--task' required placeholder='Task Title' value={this.state.tasktitle} name='tasktitle' ref='tasktitle' onChange={(event) => this.setState({ tasktitle: event.target.value })} />
<button type='submit' className='btn btn-default button--newtask' value='Submit' onClick={this.postDataHandler}>Add Task</button>
</div>
);
}
}
export default NewTask;
Here's server side to create new task
//Create New Task
exports.create_new_task = (req, res) => {
let projectid = req.params.id;
Task.create({
tasktitle: req.body.tasktitle,
taskcomment: req.body.taskcomment,
project: req.params.id
}, (err, tasks) => {
if (err) {
console.log(err);
}
Project.findById(projectid, (err, project) => {
if(err) {
console.log(err);
}
project.tasks.push(tasks._id);
project.save();
console.log('NEW Task added to project: ' + projectid)
res.json(tasks)
});
});
};
Here's my Tasks Component
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faTrashAlt, faEdit } from '#fortawesome/free-solid-svg-icons'
import './Tasks.css';
class Tasks extends Component {
constructor(props) {
super(props);
this.state = {
projectId: props._id,
tasks: []
};
}
componentDidMount() {
fetch(`/dashboard/project/${this.props.projectId}/tasks`)
.then(response => {
return response.json()
}).then(task => {
this.setState({
tasks: task.tasks
})
}).catch(error => console.error('Error:', error));
}
render() {
const fontawesomeiconStyle = {
fontSize: '1em',
color: '#8e8359',
textAlign: 'center'
}
const listStyle = {
display:'grid',
gridTemplateColumns:'2fr 1fr',
alignItems: 'center',
justifyItems: 'center'
}
const { tasks } = this.state;
return (
<div>
<ul className="task-list">
{tasks.map(task =>
<li key={task._id} style={listStyle}>{task.tasktitle}
<div>
<form method='POST' action={`/dashboard/project/${this.props.projectId}/tasks/delete?_method=DELETE&taskId=${task._id}`}>
<button className="button--tasks" >
<FontAwesomeIcon style={fontawesomeiconStyle} icon={faTrashAlt} />
</button>
</form>
</div>
</li>
)}
</ul>
</div>
);
}
}
export default Tasks;
Here's a gif so you can see what's really happening, only appends the
new task when I refresh the page..
You can return a task object from your POST method and then append to the existing task list. Something like this:
postDataHandler = () => {
/* removed for brevity */
.then(response => response.json())
.then(response => {
// append to existing list of tasks
this.props.appendTask(response);
})
.catch(error => console.error('Error:', error));
}
// method in parent component
// passed down through props
appendTask = task => {
let tasks = [...this.state.tasks];
tasks.push(task);
this.setState({tasks});
}
Your list will only re-render when a change in state affects what's being rendered. You either need to re-fetch the full list of tasks or manually append your new task, which is what's being done in the above example.
Here is a more complete example:
class TaskList extends Component {
constructor(props) {
super(props);
this.state = {
tasks: [
{/* task 1 */},
{/* task 2 */}
]
}
}
appendTask = task => {
let tasks = [...this.state.tasks];
tasks.push(task);
this.setState({tasks});
}
render() {
const { tasks } = this.state;
return (
<div className="tasks">
<ul>
{tasks.map(task => <TaskItem task={task}/>)}
</ul>
<NewTask appendTask={this.appendTask}/>
</div>
);
}
}
class NewTask extends Component {
/* ... */
postDataHandler = () => {
/* ... */
.then(response => response.json())
.then(response => {
// append to existing list of tasks
this.props.appendTask(response);
})
.catch(error => console.error('Error:', error));
}
/* ... */
}
After you POST the new item your have to GET the new item as well in your item list component.
You could put both the NewTask and TaskList components in one class component that could perform a GET after the POST promise resolves and update the state with the new item.
Or you could use Redux or another state handler that would use actions that trigger things in the right order.
Look, you're making a POST request to the backend, right?
As it seems, it gets stored correctly, but you're NOT doing anything with it. One way is to do it in a similar fashion as #wdm suggested, or just append the 'task' to your current state using setState, but only if it was posted in the first place, right? :)
Make sure that the response from the backend is the data you posted, use that response and append it to the already existing state using the ... spread operator. The setState will trigger a re-render and you'll have all your tasks listed.

Resources