I am trying to send form data life person name, email and image together using Next js. I used formdata for file upload and using react-hook-form for form input.
The problem is I couldn't receive the image/file in the Next api.
My codes are :
Onchange:
const handleImgChange = (e) => {
if (e.target.files && e.target.files[0]) {
const img = e.target.files[0];
setProfileImg(img);
}
};
to get form data from input.
const handleIChange = (e) => {
const value = e.target.value;
setContents((prevContnet) => {
return {
...prevContnet,
[e.target.name]: value,
};
});
};
On submit
const handleOnsubmlit = (e) => {
e.preventDefault();
if (profileImg.length > 0) {
const formData = { ...contents, profile_picture: profileImg };
updateUserSetting(formData);
} else {
updateUserSetting(contents);
}
};
updateUserSetting
async function updateUserSetting(formdata) {
try {
console.log("form datas", formdata);
dispatch({ type: "UPDATE_USER_SETTING_REQUEST" });
const { data } = await axios(
`${NEXT_URL}/api/updateusersetting`,
{
method: "PUT",
formdata,
"content-type": "multipart/form-data",
}
);
console.log("return data ", data[0]);
dispatch({ type: "UPDATE_USER_SETTING_SUCCESS", payload: data[0] });
} catch (error) {
dispatch({
type: "UPDATE_USER_SETTING_FAIL",
payload: error.response
});
}
}
API
import { IncomingForm } from "formidable";
export const config = {
api: {
bodyParser: false,
},
};
export default async (req, res) => {
if (req.method === "PUT") {
if (!req.headers.cookie) {
res.status(403).json({ message: "Not Authorized" });
return;
}
const { token } = cookie.parse(req.headers.cookie);
console.log("body is", req.body);
const formData = await new Promise((req, res) => {
const form = new IncomingForm();
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.writeHead(200, { "content-type": "multipart/form-data" });
res.json({ fields, files });
});
});
};
how can I put data together and send it to the desired API? Thanks in advance.
You can use the FormData interface to send files and other fields as a single JSONified string, or individual strings. Formidable will separate your fields and files in the callback, and you can process them individually.
Here's a working Codesandbox.
Output:
Related
in the following code, I'm attempting to update the Checkpoints field for one of my objects within the projects collection. UpdatedCheckpoints is working correctly, so I believe the first block of code works. But the change isn't logging to the database so it doesn't persist. What's going wrong?
const onApprovedSubmit = useCallback(
async (e) => {
e.preventDefault();
let updatedCheckpoints = props.project.Checkpoints;
updatedCheckpoints[props.checkpointIndex].checkpointSubmitted = true;
console.log('here');
try {
let projectId = props.project._id;
await fetcher('/api/projects', {
method: 'PATCH',
headers: { 'Content-type': 'application/json' },
body: JSON.stringify({ Checkpoints: updatedCheckpoints }),
id: projectId,
});
toast.success('Your checkpoint has been updated');
} catch (e) {
toast.error(e.message);
}
},
[props],
);
handler.patch(async (req, res) => {
const db = await getMongoDb();
const project = await updateProjectById(db, req.id, req.body);
res.json({ project });
});
export async function updateProjectById(db, id, data) {
return db
.collection('projects')
.findOneAndUpdate(
{ _id: new ObjectId(id) },
{
$set: data,
},
{ returnDocument: 'after' },
)
.then(({ value }) => value);
}
i want to create a user document after i sign in with google in my nextjs application. I can sign in but it's not creating the document after it. This is my function
const handleSignIn = async () => {
try {
await signIn("google");
await addUser();
} catch (error) {
console.log("Erro");
}
};
The addUser function is
const addUser = async () => {
if (status === "authenticated") {
const user = {
name: session.user.name,
email: session.user.email,
avatar: session.user.image,
};
try {
await fetch("/api/new_user", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(user),
});
} catch (error) {
console.log(error);
}
} else {
console.log("Not logged in");
}
};
This is how i'm creating the new document in my new_user.ts file in the api folder
export default async function handleNewUser(req:NextApiRequest, res:NextApiResponse){
const client = await clientPromise;
const db = client.db("bookdb");
const coll: Collection = db.collection("users");
const user = req.body
console.log(user)
try {
await coll.insertOne(user)
res.status(200).json({response:'Success'})
} catch (error) {
res.status(500).json({error:'Erro'})
To make sure it was working, i triggered manually the addUser function after signing in and it worked.
What am i doing wrong here?
this is my snippet for google auth sign in with mongodb and nextjs using typescript and prisma.
signIn: async ({user, account}) => {
if (account?.provider === 'google') {
const googleAuthData = {
name: user.name,
email: user.email,
image: user.image,
authProvider: 'google',
password: ''
}
const exist = await prisma.user.findFirst({
where: {email: user.email},
});
if (exist) {
const result = await prisma.user.update({
where: {email: user.email},
data: {image: user.image},
});
} else {
const result = await prisma.user.create({
data: googleAuthData,
});
}
}
return true;
},
i tried looking for similar answers to help solve my problem but i couldn't find anything using react redux hooks. This code was from a tutorial and originally written using the Context api. I wanted to trying using it with react-redux-hooks, but i got stuck. Basically i'm trying to register a user with a name, email and password, then pass these three as an object to the express server which will validated it and give me back a jwt token. Then come back to the client side and send the token to the reducer, which adds the token to localstorage and sets the state to isAuthenticated. The error i get is on the dispatch.
Dispatch
const onSubmit = e => {
e.preventDefault();
if (name === "" || email === "" || password === "") {
dispatch(setAlert("Please enter all fields", "danger"));
} else if (password !== password2) {
dispatch(setAlert("Passwords do not match", "danger"));
} else {
dispatch(register({ name, email, password })); // Error is here
}
setTimeout(() => {
dispatch(removeAlert());
}, 5000);
};
Action
export const register = async formData => {
const config = {
headers: {
"Content-Type": "application/json"
}
};
try {
const res = await axios.post("/api/users", formData, config);
return {
type: "REGISTER_SUCCESS",
payload: res.data
};
} catch (err) {
return {
type: "REGISTER_FAIL",
payload: err.response.data.msg
};
}
};
Reducer
const authReducer = (
state = {
token: localStorage.getItem("token"),
isAuthenticated: null,
loading: true,
user: null,
error: null
},
action
) => {
switch (action.type) {
case "REGISTER_SUCCESS":
console.log("register success");
localStorage.setItem("token", action.payload.token);
return {
...state,
...action.payload,
isAuthenticated: true,
loading: false
};
case "REGISTER_FAIL":
console.log("register failed");
localStorage.removeItem("token");
return {
...state,
token: null,
isAuthenticated: false,
loading: false,
user: null,
error: action.payload
};
default:
return state;
}
};
Store
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|| compose;
const store = createStore(
allReducers,
composeEnhancers(applyMiddleware(thunk))
);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
Express server
router.post(
"/",
[
check("name", "Please a name")
.not()
.isEmpty(),
check("email", "Please include a valid email").isEmail(),
check(
"password",
"Please enter a password with 6 or more characters"
).isLength({
min: 6
})
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array()
});
}
const { name, email, password } = req.body;
try {
let user = await User.findOne({ email });
if (user) {
return res.status(400).json({
msg: "User already exists"
});
}
user = new User({
name,
email,
password
});
// hash passsword
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
const payload = {
user: {
id: user.id
}
};
jwt.sign(
payload,
config.get("jwtSecret"),
{
expiresIn: 360000
},
(err, token) => {
if (err) throw err;
res.json({
token
});
}
);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
}
);
I believe this question has answers to the issue your experiencing here: how to async/await redux-thunk actions?
Using this example, it may look something like this (wasn't able to test it):
export const register = formData => {
const config = {
headers: {
"Content-Type": "application/json"
}
};
const request = axios.post("/api/users", formData, config);
return dispatch => {
const onSuccess = success => {
dispatch({
type: "REGISTER_SUCCESS",
payload: success.data
});
return success;
};
const onError = error => {
dispatch({
type: "REGISTER_FAIL",
payload: error.response.data.msg
});
return error;
};
request.then(onSuccess, onError);
};
};
export const register = formData => {
const config = {
headers: {
"Content-Type": "application/json"
}
};
return async dispatch => {
const onSuccess = success => {
dispatch({
type: "REGISTER_SUCCESS",
payload: success.data
});
return success;
};
const onError = error => {
dispatch({
type: "REGISTER_FAIL",
payload: error.response.data.msg
});
return error;
};
try {
const success = await axios.post("/api/users", formData, config);
return onSuccess(success);
} catch (error) {
return onError(error);
}
}
};
I am using react native document picker library to upload documents to the server my code is working perfectly but the issue is i want to show list of these selected images/documents i am not sure how to perform that action here is my code....
Document Selection code:
pickMultiple() {
try {
DocumentPicker.pickMultiple({
})
.then(images => {
this.setState({
image: null,
images: images
});
//console.log(images.length);
})
.catch(e => alert(e));
} catch (err) {
if (DocumentPicker.isCancel(err)) {
// User cancelled the picker, exit any dialogs or menus and move on
} else {
throw err;
}
}
}
Form Uploading code:
SubmitProposal = async () => {
const Uid = await AsyncStorage.getItem("projectUid");
const { params } = this.props.navigation.state;
const { amount, Description, DurationListKnown, images } = this.state;
console.log(
amount,
Description,
DurationListKnown[0],
images,
params.job_id,
images.length,
Uid
);
const formData = new FormData();
formData.append('user_id' , Uid);
formData.append('project_id' , params.job_id);
formData.append('proposed_amount' , amount);
formData.append('proposed_time' , DurationListKnown[0]);
formData.append('proposed_content' , Description);
formData.append('size' , images.length);
//formData.append('proposal_files' , images);
images.forEach((item, i) => {
// propertyData.description = this.props.description
var path = item.uri;
// var filename = path.substring(path.lastIndexOf('/')+1);
var filename = item.name;
formData.append("proposal_files"+i, {
uri: path,
type: item.type,
name: filename || `filename${i}.jpg`,
});
});
console.log(formData);
fetch('https://...proposal/add_proposal',{
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formData
}).then(response => {
if (response.status == "200") {
console.log(response);
this.showSuccessAlert();
} else if (response.status == "203") {
console.log(response);
this.showAlert();
}
}).catch((error) => {
console.log(JSON.stringify( error));
});
};
kindly help me about how can i show list of these images/documents
So I am trying to create a user using redux-form. I have an express post route on the backend. NOTE: using redux-thunk for middleware, whatwg-fetch with webpack and babel-polyfill.
routes.post('/signup', async (req, res) => {
try {
const createdUser = await userController.createUser(req.body);
const JSONCreatedUser = JSON.stringify(createdUser);
res.json({
confirmation: 'success',
result: createdUser,
});
return JSONCreatedUser;
} catch (error) {
res.statusMessage = error.toString();
res.status(409).json({
confirmation: 'failure',
error: error.toString(),
});
}
});
So the problem I am having is that when I use postman. I will get the entire user object back.
But when I submit it using form I only get
Apimanager.js
export const signUserUpApi = async (url, params) => {
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});
const { status, statusText } = response;
if (status === 409) {
throw new Error(statusText);
}
return response;
} catch (error) {
throw new Error(error.toString());
}
};
action.js
import constants from '../constants';
import { signUserUpApi } from '../utils/APIManager';
const signUserUpUrl = process.env.SIGN_USER_UP_URL || 'http://localhost:3000/user/signup';
export const signUserUp = (user) => {
return async (dispatch) => {
try {
const createdUser = await signUserUpApi(signUserUpUrl, user);
dispatch({
type: constants.SIGN_USER_UP,
user: createdUser,
});
return createdUser;
} catch (error) {
throw new Error(error);
}
};
};
export const signUserIn = (user) => {
return {
type: constants.SIGN_USER_UP,
user,
};
};
What I am trying to do is to get the User Object I created when I submit the form and redirect back to the page.
This is what I get back and it did create the user.
First thing, I need is why am I getting the https status code back and not the user object?
Second thing, what are the ways to redirect to the home page when a user successfully signed up logged in.