-
Notifications
You must be signed in to change notification settings - Fork 290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
in edit profile, i am getting req.body is undefined #155
Comments
I need to see the code to be able to help you |
So i was able to read the body using this buffer function I found in one of the issues on nextjs github issues But i am having trouble with sending profile picture to backend to be uploaded or updated.
this is the frontend code
|
What are you getting on your api end? Why are you not using any ref's like in the example? Also I don't think you need to stringify formData. |
I needed useStates instead of useRef Does using useRef instead of useState makes much of a difference in this case? |
It does, refs and state are completely different things. Personally I would try to build your form the way it is laid out in the example before changing it. |
if do this API call const updateProfile = async () => {
// e.preventDefault();
setLoading(true);
await fetch("/api/user", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
email,
baseName,
quote,
profilePicture,
}),
})
.then(async (res) => {
if (res.status === 200) {
const data = await res.json();
sessionStorage.setItem("user", JSON.stringify(data));
toast.success("Profile updated");
setLoading(false);
} else {
toast.error("Error updating profile");
setLoading(false);
}
})
.catch((err) => {
toast.error("Error updating profile");
setLoading(false);
});
}; then this is the response i get from backend server
|
ok i fixed that by removing this // validateBody({
// type: 'object',
// properties: {
// username: ValidateProps.user.username,
// },
// additionalProperties: true,
// }), i forgot to remove it earlier. only issue is that profile doesn't go as expected ok let me try using refs |
@danielmeeusen hi my code const Game = ({ logoutSound, clickSound }) => {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [verified, setVerified] = useState(false);
const [oldPassword, setOldPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [baseName, setBaseName] = useState("");
const [quote, setQuote] = useState("");
const profilePictureRef = useRef();
const [avatarUrl, setAvatarUrl] = useState(null);
const [quoteSize, setQuoteSize] = useState("");
const [loading, setLoading] = useState(false);
const updateProfile = async () => {
// e.preventDefault();
setLoading(true);
const profilePicture = profilePictureRef.current.files[0];
await fetch("/api/user", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
email,
profilePicture,
quote,
baseName,
}),
})
.then(async (res) => {
if (res.status === 200) {
const data = await res.json();
sessionStorage.setItem("user", JSON.stringify(data));
toast.success("Profile updated");
setLoading(false);
} else {
toast.error("Error updating profile");
setLoading(false);
}
})
.catch((err) => {
toast.error("Error updating profile");
setLoading(false);
});
};
return (
<>
<div className="z-[9999] fixed top-0 right-0 w-full h-screen bg-gray-500/50 flex justify-center items-center">
<div className="container mx-auto my-5 h-[90%]">
<div className="bg-black bg-[url('/images/background.png')] bg-cover bg-center rounded-lg p-10 h-full overflow-auto flex flex-col scrollable scrollable-light">
<div className="flex justify-end">
<button
draggable="false"
className="transition-transform hover:scale-95 mr-5"
onClick={() => {
setModalProfile(false);
}}
>
<ImCross className="" />
</button>
</div>
<div className="flex flex-row flex-wrap items-center my-auto">
<div className="md:basis-1/3 shrink-0 px-4 flex flex-col items-center justify-center border-r-2">
<div className="relative mb-5">
<label className="absolute top-[-5px] right-[-5px] bg-dark rounded-full p-[5px] cursor-pointer">
<CiEdit size={20} />
<input
type="file"
accept="image/*"
ref={profilePictureRef}
className="hidden"
onChange={(e) => {
const file =
e.currentTarget.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (l) => {
setAvatarUrl(
l.currentTarget.result
);
};
reader.readAsDataURL(file);
}}
/>
</label>
{avatarUrl ? (
<>
<Image
src={avatarUrl}
className="bg-dark w-20 h-20 rounded-lg"
alt={username}
width={80}
height={80}
/>
</>
) : (
<>
<div className="bg_drop bg-dark w-20 h-20 rounded-lg"></div>
</>
)}
</div>
<div className="mb-5 w-3/4">
<input
type="text"
className="border rounded-lg px-4 py-2 outline-none text-2xl bg-dark font-bold text-center w-full"
placeholder="Your Base Name"
//baseName's Base
value={baseName}
onChange={(e) => {
setBaseName(e.target.value);
}}
/>
</div>
<textarea
className="border w-3/4 outline-none p-4 bg-dark text-xl rounded-lg mb-5"
placeholder="Enter your quote here..."
value={quote}
onChange={(e) => {
setQuote(e.target.value);
}}
></textarea>
<div className="border p-4 w-3/4 rounded-lg mb-5 bg-dark">
<div className="mb-5">
<label className="text-lg">
Username
</label>
<input
type="text"
className="block border-b outline-none text-xl bg-transparent"
required
placeholder="Username"
value={username}
readonly
/>
</div>
<div className="mb-5">
<label className="text-lg">Email</label>
<input
type="email"
className="block border-b outline-none text-xl bg-transparent"
required
placeholder="Email"
value={email}
onChange={(e) => {
setEmail(e.target.value);
}}
/>
</div>
</div>
<button
draggable="false"
className="bg_drop bg-black border rounded-lg pt-2 pb-3 px-14 text-2xl font-semibold mb-4 transition-transform hover:scale-95"
onClick={updateProfile}
>
Save
{/* {loading ? <Loading /> : "Save"} */}
</button>
</div>
</div>
</div>
</div>
</div>
</>
);
}; API code import { ValidateProps } from '@/api-lib/constants';
import { findUserByEmail, updateUserById } from '@/api-lib/db';
import { auths, validateBody } from '@/api-lib/middlewares';
import { getMongoDb } from '@/api-lib/mongodb';
import { ncOpts } from '@/api-lib/nc';
// import { slugUsername } from '@/lib/user';
import { v2 as cloudinary } from 'cloudinary';
import multer from 'multer';
import nc from 'next-connect';
// import { Readable } from 'node:stream';
const upload = multer({ dest: '/tmp' });
const handler = nc(ncOpts);
if (process.env.CLOUDINARY_URL) {
const {
hostname: cloud_name,
username: api_key,
password: api_secret,
} = new URL(process.env.CLOUDINARY_URL);
cloudinary.config({
cloud_name,
api_key,
api_secret,
});
}
handler.use(...auths);
handler.get(async (req, res) => {
if (!req.user) return res.json({ user: null });
return res.json({ user: req.user });
});
async function buffer(readable) {
const chunks = [];
for await (const chunk of readable) {
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
}
return Buffer.concat(chunks);
}
handler.patch(
upload.single('profilePicture'),
// validateBody({
// type: 'object',
// properties: {
// username: ValidateProps.user.username,
// },
// additionalProperties: true,
// }),
async (req, res) => {
if (!req.user) {
req.status(401).end();
return;
}
const db = await getMongoDb();
let profilePicture;
if (req.file) {
const image = await cloudinary.uploader.upload(req.file.path, {
width: 512,
height: 512,
crop: 'fill',
});
profilePicture = image.secure_url;
}
const buf = await buffer(req);
const rawBody = buf.toString('utf-8');
const body = JSON.parse(rawBody);
const { baseName, quote, email } = body;
// let username;
if (body.email) {
// username = slugUsername(req.body.username);
if (
email !== body.email &&
(await findUserByEmail(db, email))
) {
res
.status(403)
.json({ error: { message: 'The email has already been taken.' } });
return;
}
}
const user = await updateUserById(db, req.user._id, {
// ...(username && { username }),
...(profilePicture && { profilePicture }),
...(baseName && { baseName }),
...(quote && { quote }),
...(email && { email }),
});
res.status(200).json({ user });
}
);
export const config = {
api: {
bodyParser: false,
},
};
export default handler; |
I guess you don't need a ref if you want to do it that way but you sill still need to use a formData interface though. Here is an example:
|
i added some values in the profile and want to edit them, so i did like in code here
https://github.com/hoangvvo/nextjs-mongodb-app/blob/v2/pages/api/user/index.js
but i get this error
even
console.log(req.body)
gives undefined.The text was updated successfully, but these errors were encountered: