Try to make a request to API endpoint using reactjs hook - reactjs

Endpoint
const mongoose = require("mongoose");
const CreateBio = mongoose.model("bios");
// exports.baseRoute = async (req, res) => {
// res.send("Server Running");
// };
exports.createBio = async (req, res) => {
console.log(req.body);
let userBio = new CreateBio({
userBio: req.body.userBio
});
console.log('userBio:', userBio);
await userBio.save((err, data) => {
if (err) {
// if there is an error send the following response
res.status(500).json({
message: "Something went wrong, please try again later.",
});
} else {
// if success send the following response
res.status(200).json({
message: "Bio Created",
data,
});
}
});
};
exports.displayBio = async (req, res) => {
// get id from URL by using req.params
let userBioID = req.params.id;
console.log(userBioID);
// we use mongodb's findById() functionality here
await CreateBio.findById({ _id: userBioID }, (err, data) => {
if (err) {
console.log(err)
res.status(500).json({
message: "Something went wrong, please try again later.",
});
} else {
console.log(data);
res.status(200).json({
message: "bio found",
data,
});
}
});
};
Frontend
import React, { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
import { isExpired, decodeToken } from "react-jwt";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import Container from "react-bootstrap/Container";
import Card from "react-bootstrap/Card";
import "./tests/home-test.css";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Navi from "../Navigation/nav";
import Image from "react-bootstrap/Image";
import axios from "axios";
import Nav from "react-bootstrap/Nav";
//import { displayBio } from './displayBio';
// import "./login.css";
const Home = () => {
//const [someProperty, setSomeProperty] = useState([]);
const [userBio, setBio] = useState("")
const history = useHistory();
const loadBio = async () => {
try{
let res = await axios.get('http://localhost:5000/displaybio/:id')
setBio(res.data.data.userBio)
console.log(res.data.data.userBio)
} catch (err){
console.log(err)
}
}
useEffect(() => {
// console.log("use effect working!");
if (!window.localStorage.getItem("token")) {
//redirect to login
console.log("redirect to login");
history.push("/");
}
if (window.localStorage.getItem("token")) {
const isMyTokenExpired = isExpired(window.localStorage.getItem("token"));
console.log(isMyTokenExpired);
if (isMyTokenExpired) {
console.log("redirect to login");
history.push("/");
}
const myDecodedToken = decodeToken(window.localStorage.getItem("token"));
console.log(myDecodedToken);
}
// fetch('http://localhost:5000/displayBio/:id', {
// method: "GET"
// })
// .then(res => res.json())
// .then(response => { setBio(response.item)
// })
loadBio()
}, []);
return (
<div className="Home">
<Container className="homeContainer shadow mt-2">
<Row>
<Col className="d-flex align-items-center">
<span>Home (You are logged in)</span>
</Col>
<Col className="">
<div className="d-flex align-items-center justify-content-end">
<Button
className="logoutBtn mb-2 mt-2"
onClick={(e) => {
window.localStorage.removeItem("token");
this.props.history.push("/");
}}
>
Logout
</Button>
</div>
</Col>
</Row>
<Form>
<Card className="profileCard">
<Card.Body>
<Card.Title className="text-center">
<div>
<Navi />
</div>
<h1>
Welcome Back <span className="text-success">Username</span>
</h1>
</Card.Title>
<Container>
<Row>
<Col className="d-flex justify-content-center col-12">
<div className="profilepic text-center">
Add a Profile Picture here!
</div>
</Col>
<Col className="mt-n5">
<div className="col-12 text-center">
<Card.Text
className="cardText text-center col-lg-10"
value={userBio}
//onChange={setBio}
></Card.Text>
<div className="mt-3">
<Button
className="shareVsBtn"
variant="success"
type="submit"
href="/sharewall"
>
Shared Verse
</Button>
</div>
<div className="mt-3">
<Button
className="postSubBtn mb-3"
variant="success"
type="submit"
href="/postverse"
>
Post a Verse
</Button>
</div>
</div>
</Col>
</Row>
</Container>
</Card.Body>
</Card>
</Form>
</Container>
</div>
);
}
export default Home;
Every time I try to send the request I end up getting a 500 error.500
I cannot seem to get it to console.log any of the information on the front end. I am not sure if I am not just formatting my hook right or not. I am able to get my response on the backend using postman. But my get request from the front end is not going through. Stating that I am having failure at casting {_id :id} at path _id for my model bios.

In order for you to see your userBio you need to have the handlebars inside the Card.Text selector (I omitted the className for this example). This will allow you to see the data in the front end. This is a result by taking the id from mongo and pasting it in the http address i.e: http://localhost:5000/displaybio/123456789.
<Card.Text value={userBio.id}>{userBio}</Card.Text>
In your loadBio you need to console.log(res); to find where the code is in the data object. In this case: setBio(res.data.data.userBio). This the answer to see the data displayed, Cody still needs an answer on how to grab the data dynamically by the id. displaybio/${id} doesn't work.

Related

log-in authentication with credentials, nextjs

I'm trying to add next-auth authentication with credentials(it's my first time and the source I'm using for following is using version 3 as I know, therefore there is a lot of difference and I couldn't find the right solution for days). Basically I have got form of registration and log-in form, and as a backend server I'm using mongodb. the registration form works normally, user is able to create account, but the log-in form doesn't seem to be working and in console when user sends request for logging in comes up error: {error: 'client.db.collection is not a function', status: 401, ok: false, url: null}.
This is pages/api/[...nextauth].js file.
import { verifyPassword } from "#/lib/auth";
import connectToDatabase from "#/lib/db";
import NextAuth from "next-auth/next";
import CredentialsProvider from "next-auth/providers/credentials";
export default NextAuth({
session: {
strategy: "jwt",
},
providers: [
CredentialsProvider({
async authorize(credentials, req) {
const client = await connectToDatabase();
const userCollection = client.db.collection("users");
const user = await userCollection.findOne({ email: credentials.email });
if (!user) {
client.close();
throw new Error("No user found!");
}
const isValid = verifyPassword(credentials.password, user.password);
if (!isValid) {
client.close();
throw new Error("Could not log you in.");
}
client.close();
return { email: user.email };
},
}),
],
});
and this is loginForm.js that should send request to log-in.
import React, { useRef } from "react";
import Link from "next/link";
import { signIn } from "next-auth/react";
const LoginForm = () => {
const emailRef = useRef();
const passwordRef = useRef();
const submitHandler = async (e) => {
e.preventDefault();
const enteredEmail = emailRef.current.value;
const enteredPassword = passwordRef.current.value;
try {
const result = await signIn("credentials", {
redirect: false,
email: enteredEmail,
password: enteredPassword,
});
console.log(result);
} catch (error) {
console.log(error.error);
}
};
return (
<div
className="container d-flex justify-content-center align-items-center"
style={{ width: "100%", height: "100vh" }}
>
<div className="col-6-sm">
<form onSubmit={submitHandler}>
<div className="form-outline mb-4">
<input
type="email"
id="form2Example1"
className="form-control"
ref={emailRef}
/>
<label className="form-label" for="form2Example1">
Email address
</label>
</div>
<div className="form-outline mb-4">
<input
type="password"
id="form2Example2"
className="form-control"
ref={passwordRef}
/>
<label className="form-label" for="form2Example2">
Password
</label>
</div>
<button type="submit" className="btn btn-dark m-1">
Sign in
</button>
<Link href="/register" className="btn btn-dark m-1">
Register
</Link>
</form>
</div>
</div>
);
};
export default LoginForm;

Trying to perform an update on reviews but i get no response

I'm trying to update a review then send it to my database but i get no response or error in the console, the delete is working well and deleting on the database.
'''
import React, { useState, useEffect } from 'react'
import axios from 'axios'
function Renderreview() {
const [renderReview, setRenderReview] = useState([])
useEffect(() => {
axios.get('/reviews')
.then(res => {
console.log(res)
setRenderReview(res.data)
})
.catch(err => {
console.log(err)
})
}, [])
function handleDelete(id) {
axios.delete(`/reviews/${id}`,)
}
function handleSubmit(id){
axios.update(`/reviews/${id}`,)
}
return (
<div className='card1'>
<h2>reviews</h2>
{renderReview.map((renderReview) => {
return (
<div className='renderedreviews'>{renderReview.review}
<button
onClick={() => {
handleDelete(renderReview.id);
}}
key={renderReview.review}>
Delete
</button>
<form className='reviews' onSubmit={(e) => handleSubmit(e)}>
<input onChange={(e)=>handleSubmit(e)} id="review" defaultvalue={renderReview.review} placeholder="edit" type="text"></input>
<button onClick={() =>{
handleSubmit(renderReview.id);
}}
key ={renderReview.review}
>edit review</button>
</form>
</div>
)
})}
</div>
)
}
export default Renderreview
'''
Maybe you intended to use axios.put instead of axios.update, as PUT is the method usually used to send update requests

Playing audio file from Firebase Storage works locally, but not on deployed appliation

I've been working on a prototype of AAC application for a project. Basically you hit a button, it says a word (like a sound board). I'm using firebase to host it and firebase storage to store the files. It works locally off my computer, but when I go to the deployed application, the button presses do nothing. Is there something I'm missing here? The storage addresses are redacted and replaced with "BUCKET". The url has the bucket address as well as the token attached to them. Any help would be greatly appreciated.
import React, { useState } from "react"
import { Card, Button, Alert, ButtonGroup } from "react-bootstrap"
import { useAuth } from "../contexts/AuthContext"
import { Link, useHistory } from "react-router-dom"
export default function Dashboard() {
const [error, setError] = useState("")
const { currentUser, logout } = useAuth()
const history = useHistory()
let bpYes = new Audio("BUCKET")
const pYes = () => {
bpYes.play()
}
let bpNo = new Audio("BUCKET")
const pNo = () => {
bpNo.play()
}
let bpPlease = new Audio("BUCKET")
const pPlease = () => {
bpPlease.play()
}
let bpMore = new Audio("BUCKET")
const pMore = () => {
bpMore.play()
}
let bpEat = new Audio("BUCKET")
const pEat = () => {
bpEat.play()
}
let bpDrink = new Audio("BUCKET")
const pDrink = () => {
bpDrink.play()
}
let bpPlay = new Audio("BUCKET")
const pPlay = () => {
bpPlay.play()
}
let bpPotty = new Audio("BUCKET")
const pPotty = () => {
bpPotty.play()
}
async function handleLogout() {
setError("")
try {
await logout()
history.push("/login")
} catch {
setError("Failed to log out")
}
}
return (
<>
<div className="text-center">
<h1>AAC PROTOTYPE</h1>
<h2>Welcome!</h2>
</div>
<Card>
<Card.Body>
<h2 className="text-center mb-4">Profile</h2>
{error && <Alert variant="danger">{error}</Alert>}
<strong>Email:</strong> {currentUser.email}
<Link to="/update-profile" className="btn btn-primary w-100 mt-3">
Update Profile
</Link>
</Card.Body>
</Card>
<Card>
<Card.Body>
<ButtonGroup aria-label="Basic example" class="col-md-12 text-center">
<Button size="lg" variant="outline-primary" onClick={pYes}>Yes</Button>
<Button size="lg" variant="outline-primary" onClick={pNo}>No</Button>
<Button size="lg" variant="outline-primary" onClick={pMore}>More</Button>
<Button size="lg" variant="outline-primary" onClick={pPlease}>Please</Button>
</ButtonGroup>
<ButtonGroup aria-label="Basic example" class="col-md-12 text-center">
<Button size="lg" variant="outline-primary"onClick={pEat}>Eat</Button>
<Button size="lg" variant="outline-primary"onClick={pDrink}>Drink</Button>
<Button size="lg" variant="outline-primary" onClick={pPlay}>Play</Button>
<Button size="lg" variant="outline-primary" onClick={pPotty}>Potty</Button>
</ButtonGroup>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
<Button variant="link" onClick={handleLogout}>
Log Out
</Button>
</div>
</>
)
}
Firebase doesn't support streaming audio files from storage, it works closer to a file download so a work around is needed.
Attached below is a common react script to play audio blobs from firebase storage and another for uploading.
Download and play script
const downloadAudio = async () => {
const uri = await firebase
.storage()
.ref("nameOfTheFile.filetype")
.getDownloadURL();
console.log("uri:", uri);
// The rest of this plays the audio
const soundObject = new Audio.Sound();
try {
await soundObject.loadAsync({ uri });
await soundObject.playAsync();
} catch (error) {
console.log("error:", error);
}
};
Upload as a data blob script
const uploadAudio = async () => {
const uri = recording.getURI();
try {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = () => {
try {
resolve(xhr.response);
} catch (error) {
console.log("error:", error);
}
};
xhr.onerror = (e) => {
console.log(e);
reject(new TypeError("Network request failed"));
};
xhr.responseType = "blob";
xhr.open("GET", uri, true);
xhr.send(null);
});
if (blob != null) {
const uriParts = uri.split(".");
const fileType = uriParts[uriParts.length - 1];
firebase
.storage()
.ref()
.child(`nameOfTheFile.${fileType}`)
.put(blob, {
contentType: `audio/${fileType}`,
})
.then(() => {
console.log("Sent!");
})
.catch((e) => console.log("error:", e));
} else {
console.log("erroor with blob");
}
} catch (error) {
console.log("error:", error);
}
};

Issues loading comments in Realtime

I have a social media app that I would like to function like facebook, where you comment and the comment is loaded in real-time with out having to refresh your browser to display the comment. I am able to send data from React to backend server and I am able to get that data with a axios http request, but I have to refresh the browser to see the comment displayed. I am also see the comment display more then once. I am not getting any errors but the comment is not unique to the post, as it is an array that loads the posts. Did I make a mistake in my code?
Here is the front end code.
import React, { useState, useEffect } from "react";
import Container from "react-bootstrap/Container";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import axios from "axios";
import "./css/sharewall.css";
const ComponentName = () => {
const [posts, setPosts] = useState([]);
const [comment, setComment] = useState("");
const [id, setId] = useState("");
const loadData = async () => {
try {
let res = await axios.get(`http://localhost:5000/getall`);
setPosts(res.data);
} catch (error) {
console.log(error);
}
};
function makeRequest(e) {
e.preventDefault();
axios({
method: "POST",
url: "http://localhost:5000/postinput",
data: {
comment: comment,
},
}).then((res) => {
setComment(res.data.comment);
console.log(res.data);
});
}
const loadComment = async () => {
try {
let res = await axios.post("http://localhost:5000/postinput");
setComment(res.data.comment._id);
console.log(res.data.comment._id)
} catch (error) {
console.log(error);
}
};
useEffect(() => {
loadData();
}, []);
return (
<div className="compoentclass">
<Container className="mt-5 ml-auto mr-auto">
<div className="text-center">
{posts.map((post, index) => (
<div>
<Card className="">
<Card.Img alt="" src={post.url} />
<Card.ImgOverlay className="overlay">
<Card.Title className="text-center mt-5">
<Card.Text className="cardStyle text-light">
{post.body}
</Card.Text>
</Card.Title>
</Card.ImgOverlay>
</Card>
{posts.map((post, index) => (
<div><Card.Text>{post.comment}</Card.Text></div>
))}
<textarea
className="comment text-center mt-3 mb-3"
onChange={e => setComment(e.target.value)}
value={comment}
name={"comment"}
type={"text"}
/>
<div className="d-flex justify-content-start mt-n3 mb-4">
<Button
className="shareButton"
variant="secondary"
onClick={makeRequest}
onChange={loadComment}
>
Comment
</Button>
</div>
</div>
))}
</div>
</Container>
</div>
);
};
export default ComponentName;
Here is the render from the comments, the comments double or tripple.
In order for other users (the user that posts a comment should be easily able to see the comment immediately) to see the comments real-time, you must implement some sort of "listener" to the server/database to listen for new comments. Otherwise, how should my browser know that YOU posted a comment just now? Check out socket.io, it is quite easy to implement.
I've added some additions to your code, see comments.
First, it seems you can use useEffect to rerender your comments every time you will click the "comment" button. To handle updates you can create a new state as I did.
Probably you are having troubles with multi comments because your posts array contains more than one element inside. Inside render it maps through all posts array and displays every element.
Also, would be better if you will recreate your code inside codesandbox.io or similar.
import React, { useState, useEffect } from "react";
import Container from "react-bootstrap/Container";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import axios from "axios";
import "./css/sharewall.css";
const ComponentName = () => {
const [posts, setPosts] = useState([]);
const [comment, setComment] = useState("");
const [id, setId] = useState("");
//state for resending load request
const [isCommentFetched, setCommentFetched] = useState(false);
const loadData = async () => {
try {
let res = await axios.get(`http://localhost:5000/getall`);
setPosts(res.data);
} catch (error) {
console.log(error);
}
};
function makeRequest(e) {
e.preventDefault();
axios({
method: "POST",
url: "http://localhost:5000/postinput",
data: {
comment: comment,
},
}).then((res) => {
setComment(res.data.comment);
setCommentFetched(true)
console.log(res.data);
})
//don't forget to catch errors
.catch((err)=>{
console.log(err)
})
}
const loadComment = async () => {
try {
let res = await axios.post("http://localhost:5000/postinput");
setComment(res.data.comment._id);
console.log(res.data.comment._id);
} catch (error) {
console.log(error);
}
};
useEffect(() => {
loadData();
}, []);
//hook fires whenever your isCommentFetched state updating.
useEffect(() => {
// if isCommentFetched true, it will send request for get new posts, and will update your comments in render.
if(isCommentFetched){
loadData();
}
}, [isCommentFetched]);
return (
<div className="compoentclass">
<Container className="mt-5 ml-auto mr-auto">
<div className="text-center">
{posts.map((post, index) => (
<div>
<Card className="">
<Card.Img alt="" src={post.url} />
<Card.ImgOverlay className="overlay">
<Card.Title className="text-center mt-5">
<Card.Text className="cardStyle text-light">
{post.body}
</Card.Text>
</Card.Title>
</Card.ImgOverlay>
</Card>
{posts.map((post, index) => (
<div>
<Card.Text>{post.comment}</Card.Text>
</div>
))}
<textarea
className="comment text-center mt-3 mb-3"
onChange={(e) => setComment(e.target.value)}
value={comment}
name={"comment"}
type={"text"}
/>
<div className="d-flex justify-content-start mt-n3 mb-4">
<Button
className="shareButton"
variant="secondary"
onClick={makeRequest}
onChange={loadComment}
>
Comment
</Button>
</div>
</div>
))}
</div>
</Container>
</div>
);
};
export default ComponentName;

React: Fake api's axios delete does not work

I am practicing REST API by using one Fake API site. For front-end, I am using React. I successfully login the email and password by using Fake API's login and redirect to list users, where I fetched the data from Fake API and shows the user's name, image. I used the delete button where I can delete the user. I used the Axios delete method but the button does not do anything.
This is the component
import React, { useState, useEffect } from "react";
import axios from "axios";
import { NavLink } from "react-router-dom";
function Users() {
const [state, setState] = useState([]);
useEffect(() => {
fetchingData();
}, []);
const removeData = id => { //THIS IS WHERE I USED THE AXIOS DELETE METHOD
axios
.delete(`https://reqres.in/api/users/${id}`)
.then(res => console.log(res))
.catch(err => console.log(err));
};
const fetchingData = () => {
axios
.get("https://reqres.in/api/users")
.then(response => {
setState(response.data.data);
})
.catch(err => console.log(err));
};
return (
<div>
<div className="col s12 m7">
<h2 className="header">Users</h2>
{state.map(userlist => {
return (
<div className="card horizontal" key={userlist.id}>
<div className="card-image">
<img src={userlist.avatar} alt="images" />
</div>
<div className="card-stacked">
<div className="card-content">
<p>
Name: {userlist.first_name} {userlist.last_name}
</p>
<p>Email: {userlist.email}</p>
</div>
<div className="card-action">
<button
className="btn delete"
onClick={() => removeData !== userlist.id} // THIS IS WHERE I USED THE DELETE LOGIC.
>
Delete
</button>
<NavLink
exact
to={`/api/users/${userlist.id}`}
className="btn edit"
>
Edit
</NavLink>
</div>
</div>
</div>
);
})}
</div>
</div>
);
}
export default Users;
In your delete button's onClick prop, you should pass the id as an argument.
const removeData = async id => {
console.log("ID", id);
try {
const response = await axios.delete(`https://reqres.in/api/users/${id}`);
console.log(response);
fetchingData();
} catch (error) {
console.log(error);
}
};
<button
className="btn delete"
onClick={() => removeData(userlist.id)} // THIS IS WHERE I USED THE DELETE LOGIC.
>
Delete
</button>;

Resources