React: Fake api's axios delete does not work - reactjs

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>;

Related

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

Retrieve the latest data by using API link

Goal:
Every time when I press the Button 'Test' you always need to fetch fresh data from backend by using API link. Then it should be displayed on the modalform.
Problem:
When I change the text in the input box or delete all text and then closing the modal and then click on the button Test again. The latest changes of what I have done would display. It shouldn't be happening because you always should get the latest data from backend by using API link.
Question:
How should the code always retrieve the data by using api link when you always press on the button 'test'?
Stackblitz:
https://stackblitz.com/edit/react-ts-byxk6x?file=index.tsx
Thank you!
index.tsx
import React, { FC, useState } from 'react';
import { render } from 'react-dom';
import './style.css';
import { TestModalForm } from './TestModalForm';
interface AppProps {}
interface AppState {
name: string;
}
const App: FC<AppProps> = () => {
return (
<div>
<button data-bs-toggle="modal" data-bs-target="#myModal">
Test
</button>
<br />
<TestModalForm />
</div>
);
};
render(<App />, document.getElementById('root'));
TestModalForm.tsx
import React, { useState } from 'react';
export const TestModalForm = () => {
const [inputid, setInputid] = useState('');
const [inputTitle, setInputTitle] = useState('');
React.useEffect(() => {
async function FetchData() {
var data = await fetch(
'https://jsonplaceholder.typicode.com/todos/1'
).then((res) => {
return res.json();
});
setInputid(data.id);
setInputTitle(data.title);
}
FetchData();
}, []);
const handleIdInput = (e: any) => {
setInputid(e.target.value);
};
const handleTitleInput = (e: any) => {
setInputTitle(e.target.value);
};
// Reset Input Field handler
const resetInputField = () => {
setInputid('');
setInputTitle('');
};
return (
<div>
<div
className="modal"
id="myModal"
data-bs-backdrop="static"
data-bs-keyboard="false"
tabIndex={-1}
aria-labelledby="staticBackdropLabel"
aria-hidden="true"
>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">TEST</h4>
<button
type="button"
className="btn-close btn-close-white"
data-bs-dismiss="modal"
></button>
</div>
<div className="modal-body">
<input
type="text"
className="form-control"
placeholder="Id"
value={inputid}
onChange={handleIdInput}
/>
<br />
<input
type="text"
className="form-control"
placeholder="Title"
value={inputTitle}
onChange={handleTitleInput}
/>
<br />
<button className="form-control" onClick={resetInputField}>
Reset
</button>
</div>
</div>
</div>
</div>
</div>
);
};
A simple solution would be to introduce some state to the App component, updated by the test button being clicked, that could be passed to the TestMOdalForm to be used as an useEffect dependency.
It's also anti-pattern to mix async/await with Promise-chains. Pick one or the other.
Example:
const App: FC<AppProps> = () => {
const [id, setId] = useState(0);
return (
<div>
<button
data-bs-toggle="modal"
data-bs-target="#myModal"
onClick={() => setId((c) => c + 1)} // <-- update state upon click
>
Test
</button>
<br />
<TestModalForm id={id} /> // <-- pass state as prop
</div>
);
};
...
const TestModalForm = ({ id }) => { // <-- destructure prop
...
React.useEffect(() => {
async function fetchData() {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/todos/1'
);
const data = await response.json();
setInputid(data.id);
setInputTitle(data.title);
} catch(error) {
// handle any fetch rejections or other thrown errors
}
}
fetchData();
}, [id]); // <-- pass prop as dependency
...
return (
...
);
};

My React-Firebase app is slow, how to make it faster

I am building a React-Firebase app, and the whole app was running smoothly. The authentication, the creating, logging in and logging out of the app was all very fast. Once I started to create links to the firestore, it became very slow. I have used Firebase before in instant messaging apps and it was very fast, but for some reason, it isn't anymore.
Here is the file that is causing the app to be slow:
import React, {useEffect, useState} from 'react'
import firebase from 'firebase/compat'
import { db } from '../firebase.js'
import Navbar from './Navbar'
import './styles/MasterScreen.css'
const MasterScreen = ({typeOfUser}) => {
const [customer, setCustomers] = useState([])
useEffect(() => {
async function fetchData() {
await firebase.firestore().collection('users').onSnapshot(snapshot => {
setCustomers(snapshot.docs.map(doc => doc.data()).filter(doc => doc.typeOfUser === 'customer'))
})
}
fetchData()
})
async function changeState(uid, state) {
// await db.collection('users').onSnapshot(snapshot => {
// snapshot.docs.map(doc => doc.data().uid === uid && db.collection('users').doc(doc.id).update({state}))
// })
const snapshot = await firebase.firestore().collection('users').get()
snapshot.docs.map(doc => doc.data().uid === uid && firebase.firestore().collection('users').doc(doc.id).update({state}))
}
return (
<div>
<Navbar typeOfUser={typeOfUser} />
<div className="customers">
{customers.map(e => (
<div key={e.uid} className="customer">
<div className={`state ${e.state === 'go' ? 'green' : e.state === 'slow' ? 'yellow' : e.state === 'stop' ? 'red' : 'pause'}`}>
<h3>CURRENT STATE</h3>
</div>
<div className="customerContents">
<button className='goOne btn' onClick={() => changeState(e.uid, 'go')}>GO</button>
<button className='slowOne btn' onClick={() => changeState(e.uid, 'slow')}>SLOW</button>
<button className='stopOne btn' onClick={() => changeState(e.uid, 'stop')}>STOP</button>
<button className='pauseOne btn' onClick={() => changeState(e.uid, 'pause')}>PAUSE</button>
</div>
</div>
))}
</div>
</div>
)
}
export default MasterScreen
My logic is to go inside each document in the collection and find the doc that has the same uid as the one given. Then upload the 'state' of the user to Firebase. I tried removing onSnapshot to make it faster.
If you could help, that would be create!

Try to make a request to API endpoint using reactjs hook

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.

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;

Resources