Mat*_*sen 3 reactjs next.js faunadb react-hook-form use-state
我有以下用例:
\n用户想要切换配置文件是否处于活动状态。
\n配置: \nNext.js、\nFauna DB、\nreact-hook-form
\n我使用 useState 来更改切换上的状态,并使用 React-hook-forms 将其他值发送到我的 Fauna 数据库以及切换中的状态。我希望切换具有数据库中的状态,当用户切换它并按下提交按钮时,我想更改数据库中的状态。
\n当我切换数据库时,我似乎无法将正确的状态发送回数据库。
\n主要成分:
\nexport default function Component() {\n const [status, setStatus] = useState(\n userData?.profileStatus ? userData.profileStatus : false\n );\n\nconst defaultValues = {\n profileStatus: status ? userData?.profileStatus : false\n };\n\nconst { register, handleSubmit } = useForm({ defaultValues });\n\n const handleUpdateUser = async (data) => {\n\n const {\n profileStatus\n } = data;\n try {\n await fetch(\'/api/updateProfile\', {\n method: \'PUT\',\n body: JSON.stringify({\n profileStatus\n }),\n headers: {\n \'Content-Type\': \'application/json\'\n }\n });\n alert(`submitted data: ${JSON.stringify(data)}`);\n } catch (err) {\n console.error(err);\n }\n };\n\nreturn (\n <div>\n <form onSubmit={handleSubmit(handleUpdateUser)}>\n <Toggle status={status} setStatus={setStatus} />\n <button type="submit">\n Save\n </button>\n </form>\n </div>\n )\n}\nRun Code Online (Sandbox Code Playgroud)\n切换组件:
\nimport { Switch } from \'@headlessui/react\';\n\nfunction classNames(...classes) {\n return classes.filter(Boolean).join(\' \');\n}\n\nexport default function Toggle({status , setStatus}) {\n\n return (\n <Switch.Group as="div" className="flex items-center justify-between">\n <span className="flex-grow flex flex-col">\n <Switch.Label\n as="span"\n className="text-sm font-medium text-gray-900"\n passive\n >\n Profilstatus\n </Switch.Label>\n <Switch.Description as="span" className="text-sm text-gray-500 w-44">\n Her s\xc3\xa6tter du om din profil skal v\xc3\xa6re aktiv eller inaktiv.\n </Switch.Description>\n </span>\n <Switch\n checked={status}\n onChange={setStatus}\n className={classNames(\n status ? \'bg-blue-600\' : \'bg-gray-200\',\n \'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500\'\n )}\n >\n <span\n aria-hidden="true"\n className={classNames(\n status ? \'translate-x-5\' : \'translate-x-0\',\n \'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200\'\n )}\n />\n </Switch>\n </Switch.Group>\n );\n}\nRun Code Online (Sandbox Code Playgroud)\nupdateProfile.js
\nimport { updateProfileInfo } from \'@/utils/Fauna\';\nimport { getSession } from \'next-auth/react\';\n\nexport default async (req, res) => {\n const session = await getSession({ req });\n if (!session) return res.status(401);\n\n const userId = session.user.id;\n if (req.method !== \'PUT\') {\n return res.status(405).json({ msg: \'Method not allowed\' });\n }\n\n const {\n profileStatus,\n image,\n about,\n preferences,\n socialmedia\n } = req.body;\n try {\n const updated = await updateProfileInfo(\n userId,\n profileStatus,\n image,\n about,\n preferences,\n socialmedia\n );\n return res.status(200).json(updated);\n } catch (err) {\n console.error(err);\n res.status(500).json({ msg: \'Something went wrong.\' });\n }\n res.end();\n};\nRun Code Online (Sandbox Code Playgroud)\n动物群.js
\nconst updateProfileInfo = async (\n userId,\n profileStatus,\n image,\n about,\n preferences,\n socialmedia\n) => {\n return await faunaClient.query(\n q.Update(q.Ref(q.Collection(\'users\'), userId), {\n data: {\n profileStatus,\n image,\n about,\n preferences,\n socialmedia\n }\n })\n );\n};\n\nmodule.exports = {\n updateProfileInfo\n\n}\nRun Code Online (Sandbox Code Playgroud)\n你们能看出我做错了什么吗?
\nkno*_*fel 15
我制作了一个小沙箱来演示如何使用react-hook-form.
它不起作用的原因是,react-hook-form切换开关时您永远不会更新内部状态,您只更新您的useState. 因此,当您调用handleUpdateUser作为参数传递的数据时,它是您通过设置的初始数据defaultValues。
实际上这里不需要使用useState,因为你可以只使用react-hook-form\ 的内部表单状态。为此,您必须使用 提供的<Controller />组件react-hook-form,因为<Switch />Headless UI 中的组件@headlessui/react是外部受控组件,它不会公开ref实际<input />元素的 prop(<Switch />使用 a<button />而不是<input />元素)。您可以在这里找到更多信息。
通过这种方式,您还可以通过提供 a and属性而不是and来使您的<Toggle />重用更加通用。但当然您也可以仍然使用这些名称。它将在我散布在组件上的对象上提供一个和支柱。valueonChangestatussetStatus<Controller />valueonChangefield<Toggle />
在您的示例中,尚不清楚您的<Component />组件将如何接收初始userData. 我假设您会发出 api 请求,因此我将其放入useEffect. 要在 api 调用完成后更新表单状态,您必须使用提供的reset方法react-hook-form。如果仅在已加载<Component />时进行渲染userData,则可以省略此步骤并将结果传递给defaultValuesto useForm。
我用一个简单的 Promise 模拟了 api 调用,但您应该明白了。
\n组件.js
\nimport { useEffect } from "react";\nimport { Controller, useForm } from "react-hook-form";\nimport Toggle from "./Toggle";\n\n// Server Mock\nlet databaseState = {\n profileStatus: true\n};\n\nconst getUserData = () => Promise.resolve(databaseState);\nconst updateUserData = (newState) => {\n databaseState = newState;\n\n return Promise.resolve(newState);\n};\n\nfunction Component() {\n const { control, reset, handleSubmit } = useForm({\n defaultValues: { profileStatus: false }\n });\n\n useEffect(() => {\n const loadData = async () => {\n const result = await getUserData();\n\n reset(result);\n };\n\n loadData();\n }, [reset]);\n\n const handleUpdateUser = async (data) => {\n try {\n const result = await updateUserData(data);\n\n console.log(result);\n } catch (err) {\n console.error(err);\n }\n };\n\n return (\n <div>\n <form onSubmit={handleSubmit(handleUpdateUser)}>\n <Controller\n control={control}\n name="profileStatus"\n render={({ field: { ref, ...field } }) => <Toggle {...field} />}\n />\n <button type="submit">Save</button>\n </form>\n </div>\n );\n}\nRun Code Online (Sandbox Code Playgroud)\n切换.js
\nimport { Switch } from "@headlessui/react";\n\nfunction classNames(...classes) {\n return classes.filter(Boolean).join(" ");\n}\n\nexport default function Toggle({ value, onChange }) {\n return (\n <Switch.Group as="div" className="flex items-center justify-between">\n <span className="flex-grow flex flex-col">\n <Switch.Label\n as="span"\n className="text-sm font-medium text-gray-900"\n passive\n >\n Profilstatus\n </Switch.Label>\n <Switch.Description as="span" className="text-sm text-gray-500 w-44">\n Her s\xc3\xa6tter du om din profil skal v\xc3\xa6re aktiv eller inaktiv.\n </Switch.Description>\n </span>\n <Switch\n checked={value}\n onChange={onChange}\n className={classNames(\n value ? "bg-blue-600" : "bg-gray-200",\n "relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"\n )}\n >\n <span\n aria-hidden="true"\n className={classNames(\n value ? "translate-x-5" : "translate-x-0",\n "pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200"\n )}\n />\n </Switch>\n </Switch.Group>\n );\n}\nRun Code Online (Sandbox Code Playgroud)\n\n
| 归档时间: |
|
| 查看次数: |
11035 次 |
| 最近记录: |