I am getting the comment to delete just fine, but for some reason the callback is not being invoked. I think it could be do to how I pass multiple arguments to the function maybe, but I am not sure.
I will post the code below to help out in this problem.
Show Page:
renderCommentsButtons(comment) {
const { post, user, auth } = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id) {
return (
<div>
<button
onClick={() => this.deleteComment(comment)}
className="btn btn-xs btn-danger">
Delete
</button>
<Link
to={`/posts/${post._id}/comments/${comment._id}/edit`}
className="btn btn-xs btn-warning">
Edit
</Link>
</div>
)
}
}
}
renderComments() {
const { post } = this.props;
return post.comments.map((comment) => {
return (
<li className="list-group-item" key={comment._id}>
<div>
{comment.text} : {comment.author.email}
</div>
{this.renderCommentsButtons(comment)}
</li>
);
});
}
deleteComment(comment) {
const {id} = this.props.match.params;
const {user, post, auth} = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id){
console.log('comment_id:', comment._id, 'post_id:', post._id);
this.props.deleteComments(post._id, comment._id, () => {
this.props.history.push(`/posts/${post._id}`);
});
}
}
}
Action:
export function deleteComments(post_id, comment_id, cb) {
return function(dispatch) {
console.log('comment_id:', comment_id, 'post_id:', post_id);
axios.delete(`${ROOT_URL}/${post_id}/comments/${comment_id}`)
.then(() => {
dispatch({
type: DELETE_COMMENTS,
payload: comment_id
});
})
.then(() => cb())
.catch((error) => {
console.log(error);
});
}
}
Backend:
exports.deleteComment = function(req, res, next) {
const query = {_id: req.params.comment_id};
Comments.remove(query, function(err, comments) {
if(err) {
return next(err);
} else {
res.json(comments);
}
});
}
.then(() => { dispatch(/* action */) } ) doesn't return any promise, that's why .then(() => cb()) is not executing.
You can try to call callback just after dispatching action.
axios.delete(`${ROOT_URL}/${post_id}/comments/${comment_id}`)
.then(() => {
dispatch({ /* action */})
cb();
})
.catch((error) => {
console.log(error);
});
Related
There is a list of notifications from the backend. Each notification has a delete button. If I click the delete button of any notification, I want that notification to be deleted.
How do I do this?
my service
const remove = (notificationDto) => {
return new Observable((observer) => { //<NotificationDto>
axiosInstance
.delete(SERVICE_PATH + '/remove', notificationDto)
.then((response) => {
observer.next(response.data);
observer.complete();
})
.catch((err) => {
console.log(err);
});
});
};
html
<div className="notificationlist__container only-desktop">
{props.notification.notificationList.map((notification) => {
return (
<div className="notificationlist__time">
{notification.notificationDay}
<div className="delete__button">
<AS.IconButton onClick={() => notificationDataUpdateDeleteClick(notification)}>
<AS.DeleteIcon />
</AS.IconButton>
</div>
</div>
);
})}
</div>
where i call the service
After sending notification as payload, the problem was solved
import { InAppNotificationsService } from 'services/InAppNotificationsService';
import { NotificationContext } from 'contexts/NotificationContext';
const { notificationData, setNotificationData } = useContext(NotificationContext);
const notificationDataUpdateDeleteClick = (notification) => {
InAppNotificationsService.remove({ data: notification }).subscribe({
next: (response) => {
InAppNotificationsService.allNotifications({ nationalId: tckn, externalContactNumber: contactInfo?.externalContactNumber }).subscribe({
next: (response) => {
setNotificationData(response);
},
error: (error) => {
console.log(error);
}
});
},
error: (error) => {
console.log(error);
}
});
};
So I am trying to redirect after I am deleting the page, it get's deleted from the database but it doesn't redirect me to my homepage. It worked fine when I was using json-server locally, but when I started using Mongoose it wasn't working properly and wasn't redirecting.
The code inside .then isn't working, I tried console.log inside the .then but it didn't log
I am using mongoose as my database
Here is my entire component:
import { useParams } from "react-router-dom";
import useFetch from "../useFetch";
import { useHistory } from "react-router-dom";
import moment from "moment";
import profile_image from "../images/picture.jpg";
const BlogDetails = () => {
let blogDate = moment().format('D MMM YYYY');
const { id } = useParams();
const { data: blog, isPending, errorMsg } = useFetch("http://localhost:5000/postsdata/" + id);
const history = useHistory()
const handleDelete = () => {
fetch('http://localhost:5000/postsdata/' + blog._id, { method: 'DELETE' })
.then(() => {
history.push('/');
})
.catch((err) => console.log(err))
}
return (
<div className="blog-details">
<div className="top-profile">
<div className="top-profile-picture">
<img src={profile_image} alt="profile-pic-top" />
</div>
<div className="top-profile-name">
<p>Vishwajeet Deshmukh</p>
</div>
</div>
{isPending && <div>Loading...</div>}
{errorMsg && <div>{errorMsg}</div>}
{blog && (
<article className="blog-main-content" >
<div className="main-content-header">
<div className="content-title-date">
<h2 className="blogdetails-title">{blog.title}</h2>
<p className="blogdetails-date">{blogDate}</p>
</div>
<div className="content-image">
<img src={blog.imgsrc} alt="" />
</div>
</div>
<div className="blogdetails-body"><p>{`${blog.postBody}`}</p></div>
<button className="blogdetails-delete" onClick={handleDelete}>Delete Me</button>
</article>
)}
</div>
);
};
export default BlogDetails;
Here is my router.js which handles my delete
const express = require('express');
const router = express.Router();
const { Posts } = require("./models");
//<----------------------------------- CRUD OPERATIONS ------------------------------------------>
router.get("/", () => {
console.log("Server Connected");
})
//<---------------------------- Get Posts from Database ---------------------------->
router.get("/postsdata", (req, res) => {
Posts.find((err, data) => {
if (err) {
res.status(500).send(err);
} else {
res.status(201).send(data);
}
return null;
})
})
//<------------- Get Specific Posts from Database --------------->
router.get("/postsdata/:_id", (req, res) => {
const id = req.params._id;
Posts.findById(id, (err, data) => {
if (err) {
res.status(500).send(err);
throw new Error(err)
} else {
res.status(201).send(data);
}
return data;
})
})
//<---------------------------- Post On the Posts Database ---------------------------->
router.post("/postsdata", (req, res) => {
const db = req.body;
Posts.create(db, err => {
if (!err) {
console.log("Posted on Server");
} else {
throw new Error(err)
}
return null
})
})
//<---------------------------- Delete Posts from Database ---------------------------->
router.delete("/postsdata/:id", (req, res) => {
const id = req.params._id
Posts.deleteOne(id, (err, data) => {
if (err) {
console.log(err);
throw new Error(err)
} else {
console.log(data);
}
return null
})
})
module.exports = router;
after deleting the postdata, send a response from the API.
router.delete("/postsdata/:id", (req, res) => {
const id = req.params._id
Posts.deleteOne(id, (err, data) => {
if (err) {
console.log(err);
throw new Error(err)
} else {
return res.status(200).json({status: 'success'}); // try with this
}
return null
})
})
Hello try it with async/await sayntax
const handleDelete = async () => {
await fetch('http://localhost:5000/postsdata/' + blog._id, { method: 'DELETE' });
history.push('/');
}
Ok, this is gonna be hard to explain, but I have a bug that I don't know how to fix. I have a Follow component, where i make a call to the backend to add the user as a follower/following. The function itself works, but when I change the state of the dynamicUser, that User get's added to my navBar and I can access the Profile. I'm sharing my whole code so maybe any of you guys can point me on what is wrong. Thanks in advance!
Follow component
const Follow = ({ userId, user, setUser }) => {
const [error, setError] = useState(null);
const [follow, setFollow] = useState([]);
const classes = useStyles();
const handleFollow = (e) => {
e.preventDefault();
const accessToken = localStorage.getItem(CONST.ACCESS_TOKEN);
axios
.put(
`${CONST.SERVER_URL}${PATHS.USER}/${userId}${PATHS.FOLLOW_USER}`,
{ user },
{ headers: { authorization: accessToken } }
)
.then((response) => {
console.log("BASH", response);
setError(null);
if (!response.status) {
return setError(response);
}
setUser(response?.data);
})
.catch((error) => {
console.log("ERROR", error);
});
};
const handleUnFollow = (e) => {
e.preventDefault();
const accessToken = localStorage.getItem(CONST.ACCESS_TOKEN);
axios
.put(
`${CONST.SERVER_URL}${PATHS.USER}/${userId}${PATHS.UNFOLLOW_USER}`,
{ user },
{ headers: { authorization: accessToken } }
)
.then((response) => {
console.log("Are you?", response);
setError(null);
if (!response.status) {
return setError(response);
}
setUser(response.data);
})
.catch((error) => {
console.log(error);
});
};
return (
<div>
{user.following[0] === userId ? (
<form onSubmit={handleUnFollow}>
<Button
className={classes.unFollow}
variant="contained"
color="secondary"
type="submit"
startIcon={<PersonAddDisabledIcon />}
>
UnFollow
</Button>
</form>
) : (
<form onSubmit={handleFollow}>
<Button
className={classes.follow}
variant="contained"
color="primary"
type="submit"
startIcon={<PersonAddIcon />}
>
Follow
</Button>
</form>
)}
</div>
);
};
Parent component
const SingleUser = (props) => {
const { user, setUser } = props;
const [dynamicUser, setDynamicUser] = useState({});
const [isLoading, setIsLoading] = useState(true);
const classes = useStyles();
useEffect(() => {
setIsLoading(true);
axios
.get(`${CONST.SERVER_URL}/users/${props.match.params.userId}`, {
headers: { authorization: localStorage.getItem(CONST.ACCESS_TOKEN) },
})
.then((response) => {
setDynamicUser(response.data);
})
.catch((err) => {
console.log(err.response);
})
.finally(() => {
setIsLoading(false);
});
}, [props.match.params.userId]);
if (isLoading) {
return <LoadingComponent />;
}
console.log("DYNAMIC", dynamicUser);
return (
<div>
<Grid className={classes.button} raise elevation={3}>
<Follow userId={dynamicUser._id} user={user} setUser={setUser} />
</Grid>
)
}
this will likely either solve the issue, or make it clearer from error messages where the issue is
// ...
const Follow = ({ userId, user, setUser }) => {
const [error, setError] = useState(null);
const [follow, setFollow] = useState([]);
const classes = useStyles();
const handleFollow = () => {
return new Promise(async (resolve, reject) => {
try {
const accessToken = localStorage.getItem(CONST.ACCESS_TOKEN);
const url = `${CONST.SERVER_URL}${PATHS.USER}/${userId}${PATHS.FOLLOW_USER}`
const response = await axios.put(url, { user }, { headers: { authorization: accessToken } })
console.log("BASH", response);
setError(null);
if (!response.status) throw response
setUser(response.data);
resolve()
} catch (err) {
setError(err.response.data)
console.log("ERROR", err);
reject(err)
}
})
};
// try catch blocks are easier to troubleshoot with promises
const handleUnFollow = () => {
return new Promise(async (resolve, reject) => {
try {
const accessToken = localStorage.getItem(CONST.ACCESS_TOKEN);
const url = `${CONST.SERVER_URL}${PATHS.USER}/${userId}${PATHS.UNFOLLOW_USER}`
const response = await axios.put(url, { user }, { headers: { authorization: accessToken } })
console.log("Are you?", response);
if (!response.status) throw response
setError(null);
setUser(response.data);
resolve();
} catch (err) {
console.error(err);
setError(err.response.data);
reject(err);
}
})
};
// i made some purely syntactical changes - i've always felt this was
// more readable in my own code to wite them out this way
const hasUserId = user.following[0] === userId
return (
<div>
<form
onSubmit={async e => {
e.preventDefault();
if (hasUserId) {
await handleUnFollow()
} else {
await handleFollow()
}
}}
>
<Button
className={hasUserId ? classes.unFollow : classes.follow}
variant="contained"
color={hasUserId ? 'secondary' : 'primary'}
type="submit"
startIcon={hasUserId ? <PersonAddDisabledIcon /> : <PersonAddIcon />}
>
{hasUserId ? 'UnFollow' : 'Follow' }
</Button>
</form>
</div>
);
};
const SingleUser = (props) => {
const { user, setUser } = props;
const [dynamicUser, setDynamicUser] = useState({});
const [isLoading, setIsLoading] = useState(true);
const classes = useStyles();
useEffect(() => {
return new Promise(async (resolve, reject) => {
try {
setIsLoading(true);
const url = `${CONST.SERVER_URL}/users/${props.match.params.userId}`
const headers = { authorization: localStorage.getItem(CONST.ACCESS_TOKEN) }
const response = await axios.get(url, { headers })
setDynamicUser(response.data);
setIsLoading(false);
resolve()
} catch (err) {
console.log(err.response.data);
reject(err)
}
})
// im not sure what this part does, since useEffect is never called
// however using promises is much easier to troubleshoot bugged out code
}, [props.match.params.userId]);
if (isLoading) {
return <LoadingComponent />;
}
console.log("DYNAMIC", dynamicUser);
return (
<div>
<Grid className={classes.button} raise elevation={3}>
<Follow userId={dynamicUser._id} user={user} setUser={setUser} />
</Grid>
</div>
)
}
so I ended up fixing this, and the problem was actually on the backend, cause I was sending the wrong user, but now everything works. I'll still will put my code here cause there seem to be a problem with the unFollow.
//follow user
router.put("/:userId/follow", isLoggedIn, async (req, res) => {
try {
const user = await User.findById(req.params.userId);
const currentUser = await User.findById(req.body.user._id);
const follow = await User.findByIdAndUpdate(
currentUser,
{ $addToSet: { following: user } },
{ new: true }
);
await User.findByIdAndUpdate(user, {
$addToSet: { followers: currentUser },
});
return res.json(follow);
} catch (err) {
return res.status(500).json({ error: err });
}
});
//unFollow the user
router.put("/:userId/unFollow", isLoggedIn, async (req, res) => {
try {
const user = await User.findById(req.params.userId);
const currentUser = await User.findById(req.body.user._id);
const follow = await User.findByIdAndUpdate(
currentUser,
{ $pull: { following: user } },
{ new: true }
);
await User.findByIdAndUpdate(user, {
$pull: { followers: currentUser },
});
return res.json(follow);
} catch (err) {
return res.status(500).json({ error: err });
}
});
I am looking to pass res.data back into another component. I use res.data to display results from the returned JSON into a UI.
However I would like to use res.data to conditional display certain buttons. I am using getData() to call the API.
// src/utils/debugger
let data = [];
async function getData(filter, captureName) {
if (captureName === '') {
flash('Please enter your capture name!', 5000, { color: 'red', inpType: 'danger' });
} else {
axios({
method: 'GET',
url: `http://xxx/debugger/${filter}/${captureName}/logs`,
})
.then((res) => {
if (res.data.length === 0) {
flash('No logs have been collected for this debug capture.', 5000, {
color: 'yellow',
inpType: 'warning',
});
} else {
flash('Your capture has been imported', 3000, {
color: 'green',
inpType: 'success',
});
console.log(res.data);
data = res.data;
}
return res.data;
})
.catch((err) => {
console.log(err);
});
}
}
I would like to pass res.data back into the below component so i can conditional display the buttons.
// src/component/buttons
const AllButtons = () => {
const [data, setData] = useState([]);
return (
<div>
<section id='request' className={sectionStyles}>
<div className='mt-5 inline-flex space-y-4 flex-wrap'>
<span></span>
<PrimaryBtn onClick={() => setData(adHeight())}>ad Height</PrimaryBtn>
<PrimaryBtn onClick={() => setData(adTagId())}>ad Tag Id</PrimaryBtn>
<PrimaryBtn onClick={() => setData(adWidth())}>ad Width</PrimaryBtn>
<PrimaryBtn onClick={() => setData(appBundle())}>app Bundle</PrimaryBtn>
<PrimaryBtn onClick={() => setData(appStoreUrl())}>app Store Url</PrimaryBtn>
<PrimaryBtn onClick={() => setData(askPrice())}>ask Price</PrimaryBtn>
I would like to do something like this:
// src/component/buttons
if( res.data === "someString") {
return (
<PrimaryBtn onClick={() => setData(adHeight())}>ad Height</PrimaryBtn>
<PrimaryBtn onClick={() => setData(adTagId())}>ad Tag Id</PrimaryBtn>
<PrimaryBtn onClick={() => setData(adWidth())}>ad Width</PrimaryBtn>
)
} else {
return (//something else)
}
I found it easier to use async/await with a useEffect hook,moving the flash logic inside the hook to solve this.
async function getData(filter,captureName) => {
try {
const res = await axios({
method: 'GET',
url: `http://xxx/debugger/${filter}/${captureName}/logs`,
})
return res.data
}catch(error){
throw Error(error)
}
}
const AllButtons = ({filter,captureName}) => { // assuming component receives these two props
const [data, setData] = useState([]);
useEffect(async() => {
if (captureName === '') {
flash('Please enter your capture name!', 5000, { color: 'red',
inpType: 'danger' });
}else {
try{
const response = await getData(filter, captureName) // response represents res.data
if (response.length === 0) {
flash('No logs have been collected for this debug capture.', 5000, {
color: 'yellow',
inpType: 'warning',
});
} else {
flash('Your capture has been imported', 3000, {
color: 'green',
inpType: 'success',
});
setData(response) // setting the state to be used while rendering
}
}
catch(err) {
console.log(err);
}
}
},[])
if(data === "someString") {
return (
<PrimaryBtn onClick={() => setData(adHeight())}>ad Height</PrimaryBtn>
<PrimaryBtn onClick={() => setData(adTagId())}>ad Tag Id</PrimaryBtn>
<PrimaryBtn onClick={() => setData(adWidth())}>ad Width</PrimaryBtn>
)
}else{
return (//something else)
}
}
I have action that always returns Promise.reject:
module.exports = { create: createActionAsync('CREATE_USER', () => {
return Promise.reject({
response: {
type: 'error',
message: 'It will be implemented soon',
},
});
})}
But in component catch block doesn't work:
onAddUser(data) {
const { userActions: { create } = {} } = this.props;
create(data)
.then(() => {})
.catch(err => console.error(err)) // not working