0

I am creating an 'edit profile' page for a dashboard the technologies that I use for the same are Next.js, Node.js & MongoDB.

Note: skip to the backend part if you just wanted to know the issue.

Frontend

Firstly,let me explain the Frontend part.

  • I am using useRef() inorder to reference data(name,bio) in the inputfields. which are working nicely.
  • Everything is fine the issue is in the handlesbumit() event_handler.
    • I am using FormData to send my form data to the backend API
    • If you're thinking why I'm not using a usual body object to send data the reason is that I have to add the profile picture updation later for which I have to send files , which as far I know we can't do that with an Object and yeah just to inform you it works fine if I would have used that Object part but can't use it with profilepicture updation.
    • The value that I have consoled out for the references are all good, and the rest of the handler is just as it is written can't find anything odd in that.

    import { useUser } from '../../../lib/hooks';
import React, { useState, useEffect, useRef } from 'react';
import Head from 'next/head';
import { ImBook, ImListNumbered } from 'react-icons/im';
import { AiFillGithub, AiOutlineTwitter, AiFillFacebook, AiFillInstagram, AiFillLinkedin } from 'react-icons/ai'
import { FaFacebook, FaStackOverflow } from 'react-icons/fa';

const ProfileSection = () => {
    const [user, { mutate }] = useUser();
    const [isUpdating, setIsUpdating] = useState(false);
    const nameRef = useRef();
    const profilePictureRef = useRef();
    const bioRef = useRef();
    const [msg, setMsg] = useState({ message: '', isError: false });

    useEffect(() => {
        nameRef.current.value = user.name;
        bioRef.current.value = user.Bio;
    }, [user]);


    const handleSubmit = async (event) => {
        event.preventDefault();
        if (isUpdating) return;
        setIsUpdating(true);

        console.log(nameRef.current.value); //Testing
        console.log(bioRef.current.value);  //Testing

        const formData = new FormData();
        formData.append('name', nameRef.current.value);
        formData.append('Bio', bioRef.current.value);
        console.log(formData.get('name'));
        const res = await fetch('/api/user', {
            method: 'PATCH',
            body: formData,
        });
        if (res.status === 200) {
            const userData = await res.json();
            mutate({
                user: {
                    ...user,
                    ...userData.user,
                },
            });
            setMsg({ message: 'Profile updated' });
        } else {
            setMsg({ message: await res.text(), isError: true });
        }
    };


    return (
        <>
            <Head>
                <title>Settings</title>
            </Head>
            <main>
                <div class="row">
                    <div class="col s12 m12">
                        <div className="card-panel br-10">
                            {msg.message ? <p style={{ color: msg.isError ? 'red' : '#0070f3', textAlign: 'center' }}>{msg.message}</p> : null}
                            <form onSubmit={handleSubmit}>
                                <div className="row">
                                    <div className="col s12 m6 l6">
                                        <label htmlFor="name">
                                            Name
                                         <input
                                                required
                                                id="name"
                                                name="name"
                                                type="text"
                                                ref={nameRef}
                                            />
                                        </label>
                                    </div>
                                    <div className="col s12 m6 l6">
                                        <label htmlFor="bio">
                                            Bio
                                            <textarea
                                                id="bio"
                                                name="bio"
                                                type="text"
                                                ref={bioRef}
                                            />
                                        </label>
                                    </div>
                                </div>

                                <div className="center-align">
                                    <button disabled={isUpdating} className="btn" type="submit" >Save</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </main>
        </>
    );
};

const SettingPage = () => {
    const [user] = useUser();

    if (!user) {
        return (
            <>
                <p>Please sign in</p>
            </>
        );
    }
    return (
        <>
            <ProfileSection />
        </>
    );
};

export default SettingPage;

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

    import { useUser } from '../../../lib/hooks';
    import React, { useState, useEffect, useRef } from 'react';
    import Head from 'next/head';
    import { ImBook, ImListNumbered } from 'react-icons/im';
    import { AiFillGithub, AiOutlineTwitter, AiFillFacebook, AiFillInstagram, AiFillLinkedin } from 'react-icons/ai'
    import { FaFacebook, FaStackOverflow } from 'react-icons/fa';

    const ProfileSection = () => {
        const [user, { mutate }] = useUser();
        const [isUpdating, setIsUpdating] = useState(false);
        const nameRef = useRef();
        const profilePictureRef = useRef();
        const bioRef = useRef();
        const [msg, setMsg] = useState({ message: '', isError: false });

        useEffect(() => {
            nameRef.current.value = user.name;
            bioRef.current.value = user.Bio;
        }, [user]);


        const handleSubmit = async (event) => {
            event.preventDefault();
            if (isUpdating) return;
            setIsUpdating(true);

            console.log(nameRef.current.value);
            console.log(bioRef.current.value);

            const formData = new FormData();
            formData.append('name', nameRef.current.value);
            formData.append('Bio', bioRef.current.value);
            console.log(formData.get('name'));
            const res = await fetch('/api/user', {
                method: 'PATCH',
                body: formData,
            });
            if (res.status === 200) {
                const userData = await res.json();
                mutate({
                    user: {
                        ...user,
                        ...userData.user,
                    },
                });
                setMsg({ message: 'Profile updated' });
            } else {
                setMsg({ message: await res.text(), isError: true });
            }
        };


        return (
            <>
                <Head>
                    <title>Settings</title>
                </Head>
                <main>
                    <div class="row">
                        <div class="col s12 m12">
                            <div className="card-panel br-10">
                                {msg.message ? <p style={{ color: msg.isError ? 'red' : '#0070f3', textAlign: 'center' }}>{msg.message}</p> : null}
                                <form onSubmit={handleSubmit}>
                                    <div className="row">
                                        <div className="col s12 m6 l6">
                                            <label htmlFor="name">
                                                Name
                                             <input
                                                    required
                                                    id="name"
                                                    name="name"
                                                    type="text"
                                                    ref={nameRef}
                                                />
                                            </label>
                                        </div>
                                        <div className="col s12 m6 l6">
                                            <label htmlFor="bio">
                                                Bio
                                                <textarea
                                                    id="bio"
                                                    name="bio"
                                                    type="text"
                                                    ref={bioRef}
                                                />
                                            </label>
                                        </div>
                                    </div>

                                    <div className="center-align">
                                        <button disabled={isUpdating} className="btn" type="submit" >Save</button>
                                    </div>
                                </form>
                            </div>
                        </div>
                    </div>
                </main>
            </>
        );
    };

    const SettingPage = () => {
        const [user] = useUser();

        if (!user) {
            return (
                <>
                    <p>Please sign in</p>
                </>
            );
        }
        return (
            <>
                <ProfileSection />
            </>
        );
    };

    export default SettingPage;

Backend

Now, the backend API for the same handlesubmit() event_handler i.e. 'api/user'

  • Please ignore the handler, it's just a predefined middleware npm next-connect which itself checks what type of request is coming if its 'PATCH' it will run handler.patch.
  • The Issue is the value of name & Bio is undefined,which means its not getting values from req.body;
  • And to check I also consoled out req.body which give out this enter image description here
  • The data is correct but req.body is not a Object its a String now and I get it, its because I'm using formdata so how to get the values of name & Bio from this req.body ?
    import nextConnect from 'next-connect';
import middleware from '../../../middlewares/middleware';
import { extractUser } from '../../../lib/api-helpers';

const handler = nextConnect();
handler.use(middleware);
handler.get(async (req, res) => res.json({ user: extractUser(req) }));

handler.patch(async (req, res) => {
    if (!req.user) {
        req.status(401).end();
        return;
    }

    const { name, Bio } = req.body;

    await req.db.collection('users').updateOne(
        { _id: req.user._id },
        {
            $set: {
                name:name,
                Bio: Bio,
            },
        },
    );
    res.json({ user: { name, Bio } });
});

export default handler;

1 Answer 1

1

I have encountered a this issue. I was resolve it by use 2 form, a form use to get user's info as email, password and the other for send user's picture. Maybe has best practice for this case.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.