In a component, I have a function which allows to create gardens and in another component I have a function which allows to recover these gardens which have just been created. But when I go to the screen of this component, I have to reload my application myself to see the gardens that I have just created, this is not done automatically. How can I do so that once the garden creates my GET request retrieves it automatically?
Here is my component that creates the garden:
export default function FormCreateGarden({navigation}) {
const [loading, setLoading] = useState(false);
const [garden, setGarden] = useState(false);
const [gardenName, setGardenName] = useState('');
const [gardenImage, setGardenImage] = useState({uri: '', type: '', name: ''});
const [isVisible, setIsVisible] = useState(false);
const baseUrl = 'http://127.0.0.1/api';
const submitButton = async () => {
if (!gardenName.trim()) {
alert("Veuillez renter un nom de jardin s'il vous plait!");
return;
}
setLoading(true);
try {
const jsonValue = await AsyncStorage.getItem('user');
const parsedUserData = JSON.parse(jsonValue) || {};
setUser(parsedUserData);
const myHeaders = new Headers();
myHeaders.append('Authorization', `Token ${parsedUserData.token}`);
const photo = {
uri: gardenImage.uri,
type: gardenImage.type,
name: gardenImage.name,
};
const formdata = new FormData();
formdata.append('name', gardenName);
formdata.append('user', parsedUserData.user.id);
formdata.append('image', photo);
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata,
redirect: 'follow',
};
const response = await fetch(`${baseUrl}/garden/`, requestOptions);
if (response.status === 201) {
let data = await response.json();
alert(`Votre jardin "${gardenName}" a bien été crée`);
setLoading(false);
setGardenName('');
setGardenImage({uri: '', type: '', name: ''});
navigation.navigate('GardenHome');
} else {
throw new Error('Erreur');
}
} catch (e) {
setLoading(false);
console.log(e.message);
console.log(e);
}
};
return (
<View
style={{
backgroundColor: '#32493c',
paddingLeft: 5,
paddingRight: 5,
marginLeft: 20,
}}>
<Button
title="Valider"
color={'white'}
onPress={submitButton}
/>
</View>
);
}
Here is my component that retrieves the created gardens:
export default function GardenHome() {
const [garden, setGarden] = useState([]);
const [plot, setPlot] = useState([]);
const [loading, setLoading] = useState(false);
const navigation = useNavigation();
const gardenData = async () => {
setLoading(true);
const user = await AsyncStorage.getItem('user');
const parsedUserData = JSON.parse(user);
try {
const response = await axios.get(
`http://127.0.0.1/api/garden?user=${parsedUserData.user.id}`,
{
headers: {
Authorization: `Token ${parsedUserData.token}`,
},
},
);
if (response.status === 200) {
setGarden(response.data);
setLoading(false);
}
} catch (e) {
console.log('Erreur ' + e);
setLoading(false);
}
};
useEffect(() => {
gardenData();
}, []);
}
Related
how can I run a function in the whole app? like if that function is triggered then even if a user is navigating to a different screen then also that function will do its work until that function work is done how can I do this in react native? I want to do this with my PostImageHandler once postimagehandler is triggered then that function will run and it won't stop until the image is uploaded also user can navigate through different screens during that process
const [loading1, setLoading1] = useState(false)
const [loading2, setLoading2] = useState(false)
const [photo, setPhoto] = useState(null)
const { postImage } = route.params;
const PostImageHandler = useCallback(async () => {
if (!postImage.cancelled) {
const response = await fetch(postImage);
const blob = await response.blob();
const filename = postImage.substring(postImage.lastIndexOf('/') + 1);
const ref = firebase.storage().ref().child(filename);
const snapshot = await ref.put(blob);
const url = await snapshot.ref.getDownloadURL();
setPhoto(url)
console.log(url)
}
}, [postImage])
useEffect(() => {
PostImageHandler();
}, [PostImageHandler])
const handleUpload = useCallback(() => {
if (postImage != null) {
AsyncStorage.getItem('user')
.then(data => {
setLoading2(true)
fetch('https://mybackend.com/addpost', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: JSON.parse(data).user.email,
post: postImage,
})
})
.then(res => res.json())
.then(data => {
if (data.message == 'Photo added successfully') {
alert('Photo added successfully')
setLoading2(false)
navigation.navigate('home')
} else {
alert('Something went wrong, please try again')
setLoading2(false)
}
})
})
} else {
alert('Please wait photo is processing')
}
}, [photo, navigation, setLoading2]);
I want the user to be able to add a coupon if they have one and by pressing a button the code should check if the coupon exists in my Stripe dashboard. so far I have done this(see code below), I think I'm not missing much but I can't figure out a way to send the validCoupon across from client side to server side and them being able to apply the discount there.
Cart.js (client side)
import React, {useRef, useState} from 'react';
import Link from 'next/link';
import {AiOutlineMinus, AiOutlinePlus, AiOutlineLeft, AiOutlineShopping} from 'react-icons/ai';
import {TiDeleteOutline} from 'react-icons/ti';
import toast from 'react-hot-toast';
import {useStateContext} from '../context/StateContext';
import {urlFor} from '../lib/client';
import getStripe from '../lib/getStripe';
const Cart = () => {
const cartRef = useRef();
const {
totalPrice,
totalQuantities,
cartItems,
setShowCart,
toggleCartItemQuanitity,
onRemove
} = useStateContext();
const [coupontext, setCouponText] = useState('');
const [isCouponAdded, setisCouponAdded] = useState(false);
const [validCoupon, setValidCoupon] = useState("");
const handleChange = (event) => {
setCouponText(event.target.value);
};
const checkCoupon = async () => {
if(!isCouponAdded){
const response = await fetch('https://api.stripe.com/v1/coupons', {
headers: {
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY}`
}
});
if (!response.ok) {
toast.error("Error fetching coupons");
return;
}
const {data} = await response.json();
const validcoupon = data.find((c) => c.id === coupontext);
if (validcoupon) {
toast.success("Coupon is valid!");
setValidCoupon(validcoupon);
setisCouponAdded(true);
} else {
toast.error("Coupon is invalid!");
}
}else{
toast.success("Coupon already added!");
}
}
const handleCheckout = async () => {
const stripeClient = await getStripe();
const response = await fetch('/api/stripe', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(cartItems)
});
if (response.statusCode === 500)
return;
const data = await response.json();
toast.loading('Redirecting...');
stripeClient.redirectToCheckout({sessionId: data.id});
}
.....
pages/api/stripe.js
import Stripe from 'stripe';
const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY);
export default async function handler(req, res) {
if (req.method === 'POST') {
try {
const params = {
submit_type: 'pay',
mode: 'payment',
payment_method_types: ['card'],
billing_address_collection: 'auto',
shipping_address_collection: {
allowed_countries: ["PT"],
},
shipping_options: [
{ shipping_rate: 'shr_1MMq2YJFNgzNJo7sbwDNnqhz' },
{ shipping_rate: "shr_1MMq3iJFNgzNJo7s2nVvfATq"}
],
line_items: req.body.map((item) => {
const img = item.image[0].asset._ref;
const newImage = img.replace('image-', 'https://cdn.sanity.io/images/REDACTED/production/').replace('-png', '.png');
return {
price_data: {
currency: 'eur',
product_data: {
name: item.name,
images: [newImage],
},
unit_amount: item.price * 100,
},
adjustable_quantity: {
enabled:true,
minimum: 1,
},
quantity: item.quantity
}
}),
success_url: `${req.headers.origin}/success`,
cancel_url: `${req.headers.origin}/`,
}
// Create Checkout Sessions from body params.
const session = await stripe.checkout.sessions.create(params);
res.status(200).json(session);
} catch (err) {
res.status(err.statusCode || 500).json(err.message);
}
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
}
//////////////////////////////////////// UPDATE /////////////////////////////////////////
Ok so now I'm adding validCoupon object to the cartsItems and passing in the body. on the server side I'm having issues because no discount is being applied ever, I don't know why but i fell that I'm really close to solving this, just missing something simple.
Cart.js
import React, {useRef, useState} from 'react';
import Link from 'next/link';
import {AiOutlineMinus, AiOutlinePlus, AiOutlineLeft, AiOutlineShopping} from 'react-icons/ai';
import {TiDeleteOutline} from 'react-icons/ti';
import toast from 'react-hot-toast';
import {useStateContext} from '../context/StateContext';
import {urlFor} from '../lib/client';
import getStripe from '../lib/getStripe';
const Cart = () => {
const cartRef = useRef();
const {
totalPrice,
totalQuantities,
cartItems,
setShowCart,
toggleCartItemQuanitity,
onRemove
} = useStateContext();
const [coupontext, setCouponText] = useState('');
const [isCouponAdded, setisCouponAdded] = useState(false);
const [validCoupon, setValidCoupon] = useState(null);
const handleChange = (event) => {
setCouponText(event.target.value);
};
const checkCoupon = async () => {
if(!isCouponAdded){
const response = await fetch('https://api.stripe.com/v1/coupons', {
headers: {
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY}`
}
});
if (!response.ok) {
toast.error("Error fetching coupons");
return;
}
const {data} = await response.json();
console.log(data);
const validcoupon = data.find((c) => c.id === coupontext);
if (validcoupon) {
toast.success("Coupon is valid!");
setValidCoupon(validcoupon);
setisCouponAdded(true);
} else {
toast.error("Coupon is invalid!");
}
}else{
toast.success("Coupon already added!");
}
}
const handleCheckout = async () => {
const stripeClient = await getStripe();
cartItems['validCoupon'] = validCoupon;
console.log(cartItems);
const response = await fetch('/api/stripe', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(cartItems)
});
if (response.statusCode === 500)
return;
const data = await response.json();
toast.loading('Redirecting...');
stripeClient.redirectToCheckout({sessionId: data.id});
}
pages/api/stripe.js
import Stripe from 'stripe';
const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY);
export default async function handler(req, res) {
if (req.method === 'POST') {
try {
const discounts = [];
if(req.body.validCoupon && req.body.validCoupon.id) {
discounts.push({coupon: req.body.validCoupon.id});
}
let shipping_options = [];
const line_items = req.body;
let total_amount = 0;
for (const item of line_items) {
total_amount += item.price * item.quantity;
}
if (total_amount >= 40) {
shipping_options = [
{ shipping_rate: 'shr_1MMq3iJFNgzNJo7s2nVvfATq' },
];
} else {
shipping_options = [
{ shipping_rate: "shr_1MMq2YJFNgzNJo7sbwDNnqhz"}
];
}
const params = {
submit_type: 'pay',
mode: 'payment',
discounts: discounts,
payment_method_types: ['card'],
billing_address_collection: 'auto',
shipping_address_collection: {
allowed_countries: ["PT"],
},
shipping_options: shipping_options,
line_items: req.body.map((item) => {
const img = item.image[0].asset._ref;
const newImage = img.replace('image-', 'https://cdn.sanity.io/images/REDACTED/production/').replace('-png', '.png');
return {
price_data: {
currency: 'eur',
product_data: {
name: item.name,
images: [newImage],
},
unit_amount: item.price * 100,
},
quantity: item.quantity
}
}),
success_url: `${req.headers.origin}/success`,
cancel_url: `${req.headers.origin}/`,
}
// Create Checkout Sessions from body params.
const session = await stripe.checkout.sessions.create(params);
res.status(200).json(session);
} catch (err) {
res.status(err.statusCode || 500).json(err.message);
}
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
}
You need to pass coupon to server by adding it to cartItems and you need to pass stripe coupon name in discount array in session params
import React, {useRef, useState} from 'react';
import Link from 'next/link';
import {AiOutlineMinus, AiOutlinePlus, AiOutlineLeft, AiOutlineShopping} from 'react-icons/ai';
import {TiDeleteOutline} from 'react-icons/ti';
import toast from 'react-hot-toast';
import {useStateContext} from '../context/StateContext';
import {urlFor} from '../lib/client';
import getStripe from '../lib/getStripe';
const Cart = () => {
const cartRef = useRef();
const {
totalPrice,
totalQuantities,
cartItems,
setShowCart,
toggleCartItemQuanitity,
onRemove
} = useStateContext();
const [coupontext, setCouponText] = useState('');
const [isCouponAdded, setisCouponAdded] = useState(false);
const [validCoupon, setValidCoupon] = useState("");
const handleChange = (event) => {
setCouponText(event.target.value);
};
const checkCoupon = async () => {
if(!isCouponAdded){
const response = await fetch('https://api.stripe.com/v1/coupons', {
headers: {
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY}`
}
});
if (!response.ok) {
toast.error("Error fetching coupons");
return;
}
const {data} = await response.json();
const validcoupon = data.find((c) => c.id === coupontext);
if (validcoupon) {
toast.success("Coupon is valid!");
setValidCoupon(validcoupon);
setisCouponAdded(true);
} else {
toast.error("Coupon is invalid!");
}
}else{
toast.success("Coupon already added!");
}
}
const handleCheckout = async () => {
const stripeClient = await getStripe();
cartItems['validCoupon'] = validCoupon;
const response = await fetch('/api/stripe', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(cartItems)
});
if (response.statusCode === 500)
return;
const data = await response.json();
toast.loading('Redirecting...');
stripeClient.redirectToCheckout({sessionId: data.id});
}
.....
const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY);
export default async function handler(req, res) {
if (req.method === 'POST') {
try {
const params = {
submit_type: 'pay',
mode: 'payment',
discounts: [
{
coupon: "Your_coupon_name_asper_stripe"
}
]
payment_method_types: ['card'],
billing_address_collection: 'auto',
shipping_address_collection: {
allowed_countries: ["PT"],
},
shipping_options: [
{ shipping_rate: 'shr_1MMq2YJFNgzNJo7sbwDNnqhz' },
{ shipping_rate: "shr_1MMq3iJFNgzNJo7s2nVvfATq"}
],
line_items: req.body.map((item) => {
const img = item.image[0].asset._ref;
const newImage = img.replace('image-', 'https://cdn.sanity.io/images/REDACTED/production/').replace('-png', '.png');
return {
price_data: {
currency: 'eur',
product_data: {
name: item.name,
images: [newImage],
},
unit_amount: item.price * 100,
},
adjustable_quantity: {
enabled:true,
minimum: 1,
},
quantity: item.quantity
}
}),
success_url: `${req.headers.origin}/success`,
cancel_url: `${req.headers.origin}/`,
}
// Create Checkout Sessions from body params.
const session = await stripe.checkout.sessions.create(params);
res.status(200).json(session);
} catch (err) {
res.status(err.statusCode || 500).json(err.message);
}
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
}
I included the validCoupon inside the body of the POST request.
const handleCheckout = async () => {
const stripeClient = await getStripe();
const response = await fetch('/api/stripe', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
cartItems,
validCoupon
})
});
if (response.statusCode === 500)
return;
const data = await response.json();
toast.loading('Redirecting...');
stripeClient.redirectToCheckout({sessionId: data.id});
}
then on the server side I pulled each object out of the body like this.
const {cartItems, validCoupon} = req.body;
and then used each object separately.
validCoupon.id or cartItems.map
I have a custom react hook fetching number of comments from an API that looks like this:
export async function useFetchNumberOfComments(articleId) {
const [numberOfComments, setNumbeOfComments] = useState(0);
useEffect(() => {
(async () => {
try {
const response = await axios.get(`https://example.com/${articleId}`, {
headers: {
"Content-Type": "application/json",
"X-API-KEY": "X",
Authorization: localStorage.getItem("access_token"),
},
});
const data = await response.data;
setNumbeOfComments(data);
} catch (err) {
console.log(err);
}
})();
}, []);
return numberOfComments;
}
And I want to use it in a Article component that looks like this:
import { useFetchNumberOfComments } from "../utils";
const SingleArticle = () => {
let { id } = useParams();
// Important state
const [numOfComments, setNumOfComments] = useState(0);
// Not important states
const [title, setTitle] = useState("");
const [author, setAuthor] = useState("");
const [content, setContent] = useState("");
const [comments, setComments] = useState([]);
const [commentAuthor, setCommentAuthor] = useState("");
const [commentContent, setCommentContent] = useState("");
const [imageId, setImageId] = useState("");
const [imageUrl, setImageUrl] = useState("");
const [createdAt, setCreatedAt] = useState();
const postComment = async (e) => {
e.preventDefault();
const dataToSend = {
articleId: id,
author: commentAuthor,
content: commentContent,
};
try {
await axios.post(`https://example.com/comments`, dataToSend, {
headers: {
"Content-Type": "application/json",
"X-API-KEY": "X",
Authorization: localStorage.getItem("access_token"),
},
});
// Here, fetch the number of comments from my custom hook and update numOf Comments in this component
setCommentAuthor("");
setCommentContent("");
} catch (err) {
console.log(err);
}
};
return (
<>
<form onSubmit={postComment}>
// Here are some inputs, labels and a submit button
</form>
<h4 className={styles.h1}>Comments({numOfComments})</h4>
</>
);
};
export default SingleArticle;
Now, the problem is that I have no idea how to do the mentioned activity within the Article component: Once the form data(for comment) are sent, trigger the useFetchNumberOfComments custom hook and set the numOfComments state inside article component to the newly fetched data.
I think you'd be better served refactoring the useFetchNumberOfComments hook to return a fetch function and some fetch request meta data, i.e. loading and response and error states.
Example:
export function useFetchNumberOfComments() {
const [numberOfComments, setNumbeOfComments] = useState(0);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const fetchArticleCommentCount = useCallback(async (articleId) => {
setLoading(true);
try {
const response = await axios.get(`https://example.com/${articleId}`, {
headers: {
"Content-Type": "application/json",
"X-API-KEY": "X",
Authorization: JSON.parse(localStorage.getItem("access_token")),
},
});
const data = await response.data;
setNumbeOfComments(data);
setError(null);
return data;
} catch (err) {
console.log(err);
setError(err);
} finally {
setLoading(false);
}
}, []);
return {
fetchArticleCommentCount,
numberOfComments,
loading,
error
};
};
...
import { useFetchNumberOfComments } from "../utils";
const SingleArticle = () => {
const { id } = useParams();
const {
fetchArticleCommentCount,
numberOfComments,
} = useFetchNumberOfComments();
// Important state
const [numOfComments, setNumOfComments] = useState(0);
// Not important states
...
const postComment = async (e) => {
e.preventDefault();
const dataToSend = {
articleId: id,
author: commentAuthor,
content: commentContent,
};
try {
await axios.post(`https://example.com/comments`, dataToSend, {
headers: {
"Content-Type": "application/json",
"X-API-KEY": "X",
Authorization: localStorage.getItem("access_token"),
},
});
// await returned comment count and update local state
const commentCount = await fetchArticleCommentCount(id);
setNumOfComments(commentCount);
// or use the updated numberOfComments value returned from hook
fetchArticleCommentCount(id);
// both are available, but you only need one or the other here
setCommentAuthor("");
setCommentContent("");
} catch (err) {
console.log(err);
}
};
return (
<>
<form onSubmit={postComment}>
// Here are some inputs, labels and a submit button
</form>
<h4 className={styles.h1}>Comments({numberOfComments})</h4>
</>
);
};
export default SingleArticle;
I'm using ReactJS to build a blog app. I can use axios get, put, delete but NOT POST. Every time I post a new blog, it gives me server responded with a status of 500 (Internal Server Error).
I have been struggle with this issue for a week and couldn't figure out the reason. Thank you very much for your help! Let me know if you need additional information.
Here are my codes:
API
import axios from 'axios'
const baseUrl = `/api/blogs`
let token = null
const setToken = newToken => {
token = `bearer ${newToken}`
}
const getAll = () => {
const request = axios.get(baseUrl)
return request.then(response => response.data)
}
const create = async newBlog => {
const config = {headers: { Authorization: token }}
const response = await axios.post(baseUrl, newBlog, config)
return response.data
}
const update = async (id, newObject) => {
const request = axios.put(`${baseUrl}/${id}`, newObject)
const response = await request
return response.data
}
const remove= async (id) => {
const config = {headers: { Authorization: token }}
const request = axios.delete(`${baseUrl}/${id}`, config)
const response = await request
return response.data
}
const exportedObject = { getAll, create, update, setToken, remove }
export default exportedObject
Frontend App.js
import React, { useState, useEffect, useRef } from 'react'
import blogService from './services/blogs'
import loginService from './services/login'
import Blog from './components/Blog'
import LoginForm from './components/LoginForm'
import BlogForm from './components/BlogForm'
import Togglable from './components/Togglable'
import Notification from './components/Notification'
import axios from 'axios'
const App = () => {
const [blogs, setBlogs] = useState([])
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [user, setUser] = useState(null)
const [loginVisible, setLoginVisible] = useState(false)
const [notificationText, setNotificationText] = useState("")
const [notificationStyle, setNotificationStyle] = useState("notification")
const [Toggle, setToggle] = useState(false)
const BlogFormRef = useRef()
useEffect(() => {
const Data = async () => {
const initialBlogs = await blogService.getAll()
setBlogs( initialBlogs )
}
Data()
}, [])
useEffect(() => {
const loggedUserJSON = window.localStorage.getItem('loggedBlogUser')
if (loggedUserJSON) {
const user = JSON.parse(loggedUserJSON)
setUser(user)
blogService.setToken(user.token)
}
}, [])
const addBlog = async (blogObject) => {
BlogFormRef.current.toggleVisibility()
if (blogObject.title !== '' && blogObject.author !== '' && blogObject.url !== '') {
const newBlog = await blogService.create(blogObject)
setBlogs(blogs.concat(newBlog))
setNotificationStyle('notification')
setNotificationText(`A new blog ${blogObject.title} by ${blogObject.author} is added`)
setToggle(!Toggle)
setTimeout(() => {
setToggle(false)
}, 5000)
setBlogs('')
console.log(blogObject)
document.location.reload()
} else {
setNotificationStyle('Warning')
setNotificationText('You must fill all fields to create a blog')
setToggle(!Toggle)
setTimeout(() => {
setToggle(false)
}, 5000)
}
}
Backend
const blogsRouter = require('express').Router()
const Blog = require('../models/blog')
const User = require('../models/user')
const jwt = require('jsonwebtoken')
const middleware = require("../utils/middleware")
blogsRouter.get('/', async (request, response) => {
const blogs = await Blog.find({}).populate('user', { username: 1, name: 1 })
response.json(blogs)
})
blogsRouter.get('/:id', (request, response) => {
Blog.findById(request.params.id)
.then(blog => {
if (blog) {
response.json(blog)
} else {
response.status(404).end()
}
})
})
blogsRouter.post('/', middleware.userExtractor, async (request, response) => {
const body = request.body
const user = request.user
const decodedToken = jwt.verify(request.token, process.env.SECRET)
if (!decodedToken.id){
return response.status(401).json({error: 'token missing or invalid'})
}
if(body.title === undefined){
return response.status(400).send({
error: 'title is missing'
})
}
else if(body.author === undefined){
return response.status(400).send({
error: 'author is missing'
})
}
else if(body.url === undefined){
return response.status(400).send({
error: 'url is missing'
})
}
else{
const blog = new Blog({
title: body.title,
author: body.author,
url: body.url,
likes: body.likes,
user: user.id
})
const savedBlog = await blog.save()
//console.log(savedBlog)
//console.log(user)
user.blogs = user.blogs.concat(savedBlog.id)
await user.save()
const populatedBlog = await savedBlog.populate('user', { username: 1, name: 1 }).execPopulate()
response.status(200).json(populatedBlog.toJSON())
}
})
blogsRouter.delete('/:id', middleware.userExtractor, async (request, response) => {
const blog = await Blog.findByIdAndRemove(request.params.id)
const user = request.user
const decodedToken = jwt.verify(request.token, process.env.SECRET)
if(! request.token || !decodedToken.id){
return response.status(401).json({error:'token is missing or invalid'})
}
else if(blog.user.toString() === user.id.toString()){
await Blog.findByIdAndRemove(request.params.id)
response.status(204).end()
}
else{
return response.status(401).json({error:'cannot process deletion'})
}
})
blogsRouter.put('/:id', async (request, response) => {
const body = request.body
const blog = {
title: body.title,
author:body.author,
url: body.url,
likes: body.likes
}
await Blog.findByIdAndUpdate(request.params.id, blog, { new: true })
.then(updatedBlog => {
response.json(updatedBlog)
})
})
module.exports = blogsRouter
Mongoose
const mongoose = require('mongoose')
const blogSchema = new mongoose.Schema({
title: {type:String,
required: true},
author:{type:String,
required: true},
url: {type:String,
required: true},
likes: {type:Number,
default: 0},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'}
})
blogSchema.set('toJSON', {
transform: (document, returnedObject) => {
returnedObject.id = returnedObject._id.toString()
delete returnedObject._id
delete returnedObject.__v
}
})
const Blog = mongoose.model('Blog', blogSchema)
module.exports = Blog
Additional information: terminate output, the info is actually POST just cannot render in the front
terminal output
I`m new in react, and I get problem with registration:
http.hook.js:17 POST http://localhost:3000/api/auth/register 500 (Internal Server Error)
Error: Что-то пошло не так :(, попробуйте снова
at http.hook.js:21
at async registerHandler (Registration.js:24)
code http.hook.js :
import {useState, useCallback} from 'react';
export const useHttp = () => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const request = useCallback( async (url, method = 'GET', body = null, headers = {}) => {
setLoading(true);
try {
if (body) {
body = JSON.stringify(body);
headers['Content-Type'] = 'application/json'
}
const response = await fetch(url, {method, body, headers});
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || 'Что-то пошло не так :(');
};
setLoading(false);
return data;
} catch (e) {
console.log(e)
setLoading(false);
setError(e.message);
throw e;
}
}, [])
const clearError = useCallback( () => setError(null), []);
return { loading, request, error, clearError }
}
and code Registration.js without front-end:
import React, { useState, useEffect } from 'react';
import { useHttp } from '../hooks/http.hook';
import { useMessage } from '../hooks/message.hook';
export const Registration = () => {
const message = useMessage();
const {loading, error, request, clearError} = useHttp();
const [form, setForm] = useState({
nick: '', email: '', password:''
});
useEffect(() => {
console.log(error);
message(error);
clearError();
}, [error, message, clearError]);
const changeHandler = event => {
setForm({ ...form, [event.target.name]: event.target.value });
};
const registerHandler = async () => {
try {
const data = await request('/api/auth/register', 'POST', {...form});
console.log('Data', data)
} catch (e) {
console.log(e)
}
};
I think the problem with your server-side.
HTTP response code 500 means that the server encountered an unexpected condition.
Test your endpoint by curl or XHR request.
Also maybe you send not valid data.