I'm trying to delete some information from firebase and having some trouble getting it to work.
What i'm trying to do is have the deleteRequest button delete the data pulled from the fetch link.
This is the button and method
<div class="actions">
<base-button #click="deleteRequest">Delete</base-button>
</div>
async deleteRequest() {
await this.$store.dispatch('requests/deleteRequest', {
email: this.email,
message: this.message,
artistId: this.$route.params.id,
});
async deleteRequest(context, payload) {
const removeRequest = {
userEmail: payload.email,
message: payload.message
};
const response = await fetch(`https://find-artist-d3495-default-rtdb.firebaseio.com/requests/${payload.artistId}.json`, {
method: 'DELETE',
body: JSON.stringify(removeRequest)
});
const responseData = response.json();
if (!response.ok) {
const error = new Error(responseData.message || 'Failed to send request.');
throw error;
}
context.commit('deleteRequests', removeRequest);
},
Related
I have create backend using express and mongodb database. I am trying to fetch data in react but getting an error while fetching the data as show. Please can anyone tell what the solution of above error is and how can i fetch data from the backend
const Register = () => {
const [values, setValues] = useState({
name: "",
age: "",
country: "",
email: "",
});
const setData = (e) => {
console.log(e.target.value);
const { name, value } = e.target;
setValues((val) => {
return {
...val,
[name]: value,
};
});
};
const addData = async (e) => {
e.preventDefault();
const { name, age, country, email } = values;
const res = await fetch("/register", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name,
age,
country,
email,
}),
});
const data = await res.json();
console.log(data);
if (res.status === 404 || !data) {
console.log("Error");
} else {
console.log("Data added successfully");
}
};
Here below is the backend code where the post function is performed.
router.post("/register", async (req, res) => {
const { name, age, country, email } = req.body;
if (!name || !age || !country || !email) {
res.status(404).send("Some data is missing");
}
try {
const preuser = await Crud.findOne({ email: email });
console.log(preuser);
if (preuser) {
res.status(404).send("The user already exists");
} else {
let addUser = new Crud({
name,
age,
country,
email,
});
addUser = await addUser.save();
res.status(201).json(addUser);
console.log(addUser);
}
} catch (error) {
res.status(404).send(error);
}
});
await fetch leads to an exception when the HTTP status is ≥ 400. You must add a try-catch block to handle such exceptions:
try {
const res = await fetch("/register", {...});
} catch(exception) {
// Handle the exception
}
Also, HTTP status 404 should be used when a resource is not found. You use it when a user already exists (where status 400 would be more appropriate) or in case of a database error (when 500 would be more appropriate).
i have a function called login that redirects the user to the main page if everything was ok. Then, on the main page, i want to fetch some user info with useEffect using the token the was stored when the user logged in, but nothing happens. Only when i refresh the page i get the data.
login function
export const login = ({ email, password, history }) => {
return async (dispatch) => {
try {
const response = await fetch("http://localhost:5000/api/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email,
password,
}),
});
const data = await response.json();
if (data.status === 200) {
localStorage.setItem("userToken", data.user);
history.push("/");
} else {
dispatch(
setNotification({
variant: "error",
message: data.message,
})
);
}
} catch (e) {
console.log(e.message);
}
};
};
fetch user funtion
export const fetchUser = () => {
return async (dispatch) => {
try {
const response = await fetch("http://localhost:5000/userInfo", {
headers: {
"x-access-token": localStorage.getItem("userToken"),
},
});
const data = await response.json();
dispatch(setUser({
id: data.id,
fullname: data.fullname,
email: data.email
}))
} catch (error) {}
};
};
useEffect on my main page
useEffect(() => {
dispatch(fetchUser());
}, []);
backend function
module.exports.getCurrentUser = async (req, res) => {
const token = req.headers["x-access-token"];
try {
const verifyToken = jwt.verify(token, "123");
const user = await User.findOne({ email: verifyToken.email });
return res.json({
id: user._id,
fullname: user.fullname,
email: user.email
})
} catch (error) {}
};
The 2nd parameter to useEffect tells it when it needs to run. It only runs if one of the values in the array has changed. Since you pass an empty array, none of the values in it have changed.
This is presuming your app probably starts at '/', then detects there is no user so switches to the login screen. When it goes back to the root, it only executes useEffect if something in the array has changed from the previous render.
As it is, the isMounted doesn't make much sense. This could simply be:
useEffect(() => {
dispatch(fetchUser());
});
You're calling setUser, but what is calling your login function?
I'm trying to figure out how to delete information submitted to the firebase database.
I am trying to delete information under the requests. Example
Here are my actions used to fetch the data:
export default {
async contactArtist(context, payload) {
const newRequest = {
userEmail: payload.email,
message: payload.message
};
const response = await fetch(`https://find-artist-d3495-default-rtdb.firebaseio.com/requests/${payload.artistId}.json`, {
method: 'POST',
body: JSON.stringify(newRequest)
});
const responseData = await response.json();
if (!response.ok) {
const error = new Error(responseData.message || 'Failed to send request.');
throw error;
}
newRequest.id = responseData.name;
newRequest.artistId = payload.artistId;
context.commit('addRequest', newRequest);
},
async fetchRequests(context) {
const artistId = context.rootGetters.userId;
const token = context.rootGetters.token;
const response = await fetch(`https://find-artist-d3495-default-rtdb.firebaseio.com/requests/${artistId}.json?auth=` + token);
const responseData = await response.json();
if (!response.ok) {
const error = new Error(responseData.message || 'Failed to fetch requests.');
throw error;
}
const requests = [];
for (const key in responseData) {
const request = {
id: key,
artistId: artistId,
userEmail: responseData[key].userEmail,
message: responseData[key].message
};
requests.push(request);
}
context.commit('setRequests', requests);
},
};
I'm trying to set up a button that will delete the selected request object.
Your code is sending a POST request, which tells Firebase to generate a unique key. From the documentation on saving data:
POST: Add to a list of data in our Firebase database. Every time we send a POST request, the Firebase client generates a unique key, like fireblog/users/<unique-id>/<data>
The delete a node, send the DELETE verb/method to that path:
const response = await fetch(`https://find-artist-d3495-default-rtdb.firebaseio.com/requests/${payload.artistId}.json`, {
method: 'DELETE'
});
I am getting an email from lstate which is a state of useReducer. I am getting lstate value by using Context api and useContext. But my problem is that i transfered the lstate using fetch api to my backend auth.js to get the document of the required email from the MongoDB. But i am not getting email from lstate at backend i am getting objects.
Account.jsx
const Account = () => {
const { lstate } = useContext(LoginContext);
const LoginData = async () => {
console.log(`my lstate in login function ${lstate}`);
await fetch('/account', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
lstate
})
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
})
}
useEffect(() => {
LoginData();
}, []);
auth.js
router.post('/account', async (req, res) => {
try {
const email = req.body;
console.log(`data from account ${email}`);
const data = await CustomerModel.findOne({ email: email });
if (data) {
return res.json(data);
}
} catch (error) {
console.log(error);
}
})
Console Error
data from account [object Object]
CastError: Cast to string failed for value "{ lstate: 'usman4276#gmail.com' }" at path "email" for model "Customer_reg"
at model.Query.exec (C:\MERN stack\online-cattle-shop\backend\node_modules\mongoose\lib\query.js:4408:21)
at model.Query.Query.then (C:\MERN stack\online-cattle-shop\backend\node_modules\mongoose\lib\query.jsbackend\node_modules\mongoose\lib\query.js:4502:15)
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
messageFormat: undefined,
stringValue: `"{ lstate: 'usman4276#gmail.com' }"`, kind: 'string',
value: { lstate: 'usman4276#gmail.com' },
path: 'email',
reason: null
}
should be
const { email } = req.body;
OR
const email = req.body.email;
You should also add conditional checks.
E.g.
if (!email) throw new Error ('Email Required')
The code in the client is sending a JSON and the key lstate contains the actual mail.
you need to do
const email = req.body.email.lstate;
const data = await CustomerModel.findOne({ email });
I am creating a MERN app, I am new to this. I tried following some tutorials on the net but I have encountered some error.
I am submitting the post request like this. As you can see I am not specifying the content type because I know that if you are using the 'multipart/form-data it will automatically append it to the headers. I am using a react hook here which is why I am not directly using the fetch method.
const formData = new FormData();
formData.append("email", formState.inputs.email.value);
formData.append("name", formState.inputs.name.value);
formData.append("password", formState.inputs.password.value);
formData.append("image", formState.inputs.image.value);
const responseData = await sendRequest(
`${process.env.REACT_APP_BACKEND_BASE_URL}/api/users/signup`,
"POST",
formData
);
meanwhile my signup route is like this, UNDER user-routes.js
router.post(
"/signup",
fileUpload.single("image"),
[
check("name").not().isEmpty(),
check("email")
.normalizeEmail() // Test#test.com => test#test.com
.isEmail(),
check("password").isLength({ min: 6 }),
],
usersController.signup
);
as you can also see, I am catching it in the route by using the fileUpload.single("image")
if you need to see my hook that I am using here it is, but I am pretty sure that the hook works fine. and it has no issues whatsoever, so here it is: this is a react hook
export const useHttpClient = () => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState();
const activeHttpRequests = useRef([]);
const sendRequest = useCallback(
async (url, method = "GET", body = null, headers = {}) => {
setIsLoading(true);
const httpAbortCtrl = new AbortController();
activeHttpRequests.current.push(httpAbortCtrl);
try {
const response = await fetch(url, {
method,
body,
headers,
signal: httpAbortCtrl.signal,
});
const responseData = await response.json();
// console.log("Response: ", response);
// console.log("Data: ", responseData);
activeHttpRequests.current = activeHttpRequests.current.filter(
(reqCtrl) => reqCtrl !== httpAbortCtrl
);
if (!response.ok) {
throw new Error(responseData.message);
}
setIsLoading(false);
return responseData;
} catch (err) {
setError(err.message);
setIsLoading(false);
throw err;
}
},
[]
);
const clearError = () => {
setError(null);
};
useEffect(() => {
return () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
activeHttpRequests.current.forEach((abortCtrl) => abortCtrl.abort());
};
}, []);
return { isLoading, error, sendRequest, clearError };
};
I will include the signup here from my users.controller:
const signup = async (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return next(
new HttpError("Invalid inputs passed, please check your data.", 422)
);
}
const { name, email, password } = req.body;
let existingUser;
try {
existingUser = await User.findOne({ email: email });
} catch (err) {
const error = new HttpError(
"Signing up failed, please try again later.",
500
);
return next(error);
}
if (existingUser) {
const error = new HttpError(
"User exists already, please login instead.",
422
);
return next(error);
}
let hashedPassword;
try {
hashedPassword = await bcrypt.hash(password, 12);
} catch (err) {
const error = new HttpError(
"Could not create user, please try again.",
500
);
return next(error);
}
//res.json({ message: "AFTER HASHING" });
const createdUser = new User({
name,
email,
image: req.file.path,
password: hashedPassword,
places: [],
});
try {
await createdUser.save();
} catch (err) {
const error = new HttpError(
"Signing up failed, please try again later.",
500
);
return next(error);
}
let token;
try {
token = jwt.sign(
{ userId: createdUser.id, email: createdUser.email },
process.env.JWT_KEY,
{ expiresIn: "1h" }
);
} catch (err) {
const error = new HttpError(
"Signing up failed, please try again later.",
500
);
return next(error);
}
res
.status(201)
.json({ userId: createdUser.id, email: createdUser.email, token: token });
};
You may want to use JSON.Parse() around your responseData
When ever I run into this bug it is because I either,
parsed an already parsed object
Stingified a string
Used a string as an object
This link goes into more depth about the bug and common ways of dissecting the issue.
Try console.log() in your hook before you send the data and also log what the responseData looks like after it retrieves the data