Show detail Button in table not working(instead pages gets reload) and Not getting all the data properly of the table from mongodb - node.js

As I click on the Show detail button I should get an alert/more info of the user but instead of that the page gets reload. Basically on 'show details' button the 'OnClick' function is not getting executed.
Why am I getting no enteries found after clicking on 'show details'
Fetching data from Database and setting it in 'clientTable' variable:
React.useEffect(()=>{
window.onload=()=>{
const datatablesSimple = document.getElementById('datatablesSimple');
if (datatablesSimple) {
new DataTable(datatablesSimple);
}
const fetchClients = async ()=>{
const res = await axios.get("/users")
setClientTable((clientTable)=>{return clientTable=res.data;})
console.log(clientTable)
}
fetchClients()
}
},[]);
Nodejs code for fetching all the Clients
router.get("/", async(req, res) => {
try{
const allclients = await User.find();
res.status(200).json(allclients);
}catch(err){
res.status(500).json(err);
}
});
HTML code of rendering the table in frontend:
<tbody>
{clientTable.map((User, index)=>(<>
<tr key={index}>
<td>
<Link to="/details" state={User}
style={{textDecoration:'none',
color:'black'}} > {User.username}
</Link>
</td>
<td>{User.email}</td>
<td>{User.dob}</td>
<td>{User.city}</td>
<td>{User.services}</td>
<td><button onClick={handleRowClick}> show details</button></td>
</tr>
</>
))}
</tbody>
handleRowClick method implementation:
const handleRowClick = (e) => {
e.preventDefault();
alert("Hello")
//setShowPopup(true);
}

Related

React JS Modal Show White Blank Screen

I have a data called person in JSON format getting from API in the file User.js:
const [person, setPerson] = useState([]);
const url = "http://localhost:8080/api/persons";
useEffect(() => {
axios.get(url).then((response) => {
setPerson(response.data);
});
}, [url]);
In another file called UpdatePersonForm.js I'm trying to show that data in popup windows after clicking a button.
export const UpdatePersonForm= ({ person, personEditOnSubmit }) => {
return (
<div>
{person.map((item) => (
<tr>
<td>{item.name}</td>
</tr>
))}
</div>
}
then it shows a white blank screen again. If I called an API directly from UpdatePersonForm.js then it works fine. For example:
export const UpdatePersonForm= ({ personEditOnSubmit }) => {
const [person, setPerson] = useState([]);
const url = "http://localhost:8080/api/persons";
useEffect(() => {
axios.get(url).then((response) => {
setPerson(response.data);
});
}, [url]);
return (
<div>
{person.map((item) => (
<tr>
<td>{item.name}</td>
</tr>
))}
</div>
}
However, if I get data from the parent file like the above then I got wrong.
You initialize the person variable with const [person, setPerson] = useState(""); which means that on first render person will be a string and strings do not have a .map method.
Use const [person, setPerson] = useState([]); and you should be fine.
Since you expect it to be an array after the JSON is fetched, you should also initialize it to one.

TypeError: users.map is not a function React js

am stuck with a problem , am try to solve it lots of time but am not able to solve it , please try to fix my error. If you have any query please free feel to ask.
Userdata.js
This is the userdata.js file where I want to load my all data which are in backend database
import React, { useEffect, useState } from "react";
import { Link,useParams } from "react-router-dom";
import Axios from 'axios';
const UserData = () => {
const [users, setUser] = useState({
title : "",
description : ""
});
const {id} = useParams();
useEffect(() => {
AllUsers();
}, []);
const AllUsers = async () => {
const res = await Axios.get(`http://localhost:3000/${id}`);
console.log(res.data);
setUser(res.data)
};
return (
<div>
<div className="container">
<table className="table table-hover table-bordered mt-5">
<thead>
<tr>
{/* <th scope="col">No</th> */}
<th scope="col">Title</th>
<th scope="col">Details</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{users.map((user, index) => (
<tr key={index}>
<th scope="row">{user.id}</th>
<td>{user.title}</td>
<td>{user.description}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
export default UserData;
users looks to me to be an object, not an array. The map() function exists only on Array's prototype, so you can't call it on your users object. Did you mean to initialize users like this?
const [users, setUser] = useState([{
title : "",
description : ""
}]);
The map method is defined on on array and not on objects. Lets look at your code
const [users, setUser] = useState({
title : "",
description : ""
});
In UserData component you defined an object state with properties title and description. So users will be an object with those properties. Thus when you try to apply map on the users object it fails since map is not a function defined on objects.
Instead if you want to have an array of users with those two properties you can declare the state as follows
const [users, setUser] = useState([{
title : "",
description : ""
}]);

Fetch Data from mongoDb using ReactJs and node

I have a mern project where i want to fetch data from mongodb in my reactjs.
I have gone through sevral previous question but it didn't help!
i have successfully fetched all data all together
But i want to fetch olny specific data ilke email. How can i do that?
Admin.js(frontend)
import React from 'react';
import axios from 'axios';
class Admin extends React.Component {
state = {
phone: '',
email: '',
posts: []
};
// componentDidMount = () => {
// this.getBlogPost();
// };
hello = () => {
axios.get('/getuser')
.then((response) => {
const data = response.data;
this.setState({ posts: data });
console.log(data);
})
.catch(() => {
alert('Error retrieving data!!!');
});
}
displayBlogPost = (posts) => {
if (!posts.length) return null;
return posts.map((post, index) => (
<div key={index} className="blog-post__display">
<h3>{post.phone}</h3>
<p>{post.email}</p>
</div>
));
};
render() {
return (
<>
<h1>
<button onClick={this.hello} class="btn btn-danger">click here to get data</button>
</h1>
<div className="blog-">
{this.displayBlogPost(this.state.posts)}
<table>
<tr>
<th>email</th>
<th>phone</th>
</tr>
<tr>
<td>rah098755#gmail.com</td>
<td>8340251638</td>
</tr>
<tr>
<td>kumar_rahulkkcs#yahoo.com</td>
<td>78750251638</td>
</tr>
<tr>
<td>anita#gmail.com</td>
<td>9652251638</td>
</tr>
</table>
</div>
</>
)
}
}
export default Admin;
i am getting data in my browser like this---
How can i show olny specific data
thankyou
So I am going to assume you have an Express App running with endpoints you are calling from this front-end code given the /get-user endpoint. The endpoint returns all of the user data for one or more users depending on how you set it up. In order to get a list emails for users, you will need something to distinguish your API call to the Express App that you want only the emails for the users, and not the full user object. There are a lot of ways to make this distinction, but another route is probably the best option to adhere to REST in some way. Below is a possible example:
Express Endpoint
app.get('/users/email', (req, res) => {
Call MongoDB and filter the user list to just email for response
}
REACT Call
emails = () => {
axios.get('/users/email')
.then((response) => {
const data = response.data;
this.setState({ emails: data });
console.log(data);
})
.catch(() => {
alert('Error retrieving data!!!');
});
}
It is in the Express app that you should filter and ideally sort data for the front-end app to consume. Otherwise you risk sending too much data to the front-end or sending sensitive data by accident. Take a look at the below link for a bit more robust example.
https://codingthesmartway.com/the-mern-stack-tutorial-building-a-react-crud-application-from-start-to-finish-part-1/

Show added posts without refreshing page in React

I have been working on a personal project outside university, developing a blog.
Right now I'm trying to implement a "home page" where after a succesfull login, the user can post text, and right after that it appears under the Create post div you can see in the pic
This is what I have managed to accomplish so far:
This is the home page after login
Right now I can login, and post a new post which saves it in the database.
This is the home.js functional componenet which the user sees after a login:
import '../App.css';
import { useHistory } from "react-router-dom";
import React , {useState, useEffect} from 'react';
import jwt_decode from 'jwt-decode'
import logo from '../images/home-logo.png';
import {Col,Form,Input,Button,Card,CardTitle,Navbar,Nav,NavbarBrand} from 'reactstrap'
import { createPost,getUserPosts } from '../fucntions/user_functions'
function Home(){
var _decoded;
var _email;
let history = useHistory();
const[post_text,setPost] = useState('');
const handleChangePost = e =>{ setPost(e.target.value);};
function handlePost(e){
e.preventDefault();
const toPost = {
post :post_text, email :_email
}
createPost(toPost).then(res =>{
setPost('')
})
}
function getPosts() {
const container ={
email:_email
}
getUserPosts(container).then(res=>{
})
}
function handleLogout (e) {
e.preventDefault();
localStorage.removeItem('usertoken')
history.push(`/login`)
}
useEffect(() =>{
if (localStorage.getItem("usertoken") === null) {
history.push('/login')
} else {
const token = localStorage.usertoken
const user_email = localStorage.useremail
const decoded = jwt_decode(token)
_decoded = decoded;
_email = decoded.email
getPosts()
};
});
return (
<div className = "box">
<div>
<Navbar color="light" light expand="md">
<Nav>
<NavbarBrand type = "button" onClick = {handleLogout}>Logout</NavbarBrand>
</Nav>
</Navbar>
<div className = "wrapper">
<Card body outline color="secondary" className = "card-home " >
<CardTitle><img src={logo} alt="logo"></img>Create post</CardTitle>
<Form onSubmit = {handlePost}>
<Input id = "tx" name = "input1" type = "textarea" value = {post_text} placeholder="Enter your post here" onChange= {handleChangePost}></Input>
<br></br>
<Col sm={{ span: 10, offset: 5 }}>
<Button outline color="primary" type="submit">Post!</Button>
</Col>
</Form>
</Card>
</div>
</div>
</div>
)
}
export default Home;
I have implemented a getPosts method in the backend which gives back an array of the posts
router.post("/getPosts",
async (req, res) => {
const {email,} = req.body;
try {
let user = await User.findOne({email:email});
allPosts = user.posts
res.render('/home',{posts : hello})
} catch (e) {
console.error(e);
res.json("Error")
}
}
);
As you can see above, in the function getPosts(), the response is an Array of all the post's ids the user has posted, they are stored in the mongodb collection called "posts"
And after calling that function, I can iterate over them:
function getPosts() {
const container ={
email:_email
}
getUserPosts(container).then(res=>{
forEach(res.posts) {
}
})
}
I want to render all those posts live, so each time the user posts a new post, it will show right after the Create post div you can see in the picture, What's the best way?
Thanks
First define your posts collection state:
const [allPosts, setAllPosts] = useState([]);
Then every time you successfully save a post in the database, append it to that state:
function handlePost(e){
e.preventDefault();
const toPost = {
post :post_text, email :_email
}
createPost(toPost).then(res =>{
setPost('')
setAllPosts(allPosts.concat(toPost);
})
}
The same goes for getPosts:
function getPosts() {
const container ={
email:_email
}
getUserPosts(container).then(res=>{
setAllPosts(res.data); // <-- if the data is the same structure as the created before
})
}
Then you can render them in an example way:
return (
<div className = "box">
<div>
<Navbar color="light" light expand="md">
<Nav>
<NavbarBrand type = "button" onClick = {handleLogout}>Logout</NavbarBrand>
</Nav>
</Navbar>
<div className = "wrapper">
<Card body outline color="secondary" className = "card-home " >
<CardTitle><img src={logo} alt="logo"></img>Create post</CardTitle>
<Form onSubmit = {handlePost}>
<Input id = "tx" name = "input1" type = "textarea" value = {post_text} placeholder="Enter your post here" onChange= {handleChangePost}></Input>
<br></br>
<Col sm={{ span: 10, offset: 5 }}>
<Button outline color="primary" type="submit">Post!</Button>
</Col>
</Form>
<div>
{
allPosts.map(post => {
return <div><div>email: {post.email}</div><div>post: post.post</div></div>
})
}
</div>
</Card>
</div>
</div>
</div>
)
Feel free to change the HTML structure, so it matches your design

How do I have a variable available to display on my success page, after adding items to a database via a /POST route?

I would like to display the doc.id variable of a successful /POST of data to a route, on the success page that the user will be redirected to afterward. I'm trying to work out how to carry the variable teamId through to the Handlebar template page success.hbs
I've tried making it a variable, and setting up a Handlebar helper to display it, but nothing is working.
/POST route redirecting to success.hbs:
app.post('/create', (req, res) => {
var players = [];
var playerObj = {};
for (let i = 1; i < 21; i++) {
var playerObj = { playerName: req.body[`player${i}Name`], playerNumber: req.body[`player${i}Number`], playerPosition: req.body[`player${i}Position`] };
if (req.body["player" + i + "Name"] === '') {
console.log("Empty player name detected, disregarding");
} else {
players.push(playerObj);
}
}
var newTeam = new Team({
// WEB SETUP BELOW
"team.teamRoster.teamCoach": req.body.coachName,
"team.shortTeamName": req.body.teamShortName,
"team.teamName": req.body.teamName,
"team.teamRoster.players": players
});
newTeam.save().then((doc) => {
var teamId = doc.id;
console.log(teamId);
res.render('success.hbs');
console.log("Team Added");
}, (e) => {
res.status(400).send(e);
});
});
/views/success.hbs
<div class="container-fluid" id="body">
<div class="container" id="page-header">
<h1><span id="headline">Team Added Succesfully</span></h1>
<hr>
<h3><span id="subheadline">Input the following address as a JSON Data Source within vMix.</span></h3>
<span id="content">
<div class="row">
<div class="container col-md-12">
{{{teamId}}}
</div>
</div>
</span>
</div>
<hr>
</div>
I'd like a Handlebar helper to get the doc.id value of the /POST request, and store it as teamId to display on the success page. It's finding nothing at the moment.
Any help is appreciated.
Node.js can pass variables to the handlebars-view like this:
newTeam.save().then((doc) => {
var teamId = doc.id;
console.log(teamId);
res.render('success.hbs', {
teamId
});
console.log("Team Added");
}, (e) => {
res.status(400).send(e);
});

Resources