- 背景
- 记录
- tailwindcss的scrollbar
- prisma的env没有读取到dababase_url
- 登陆怎么做?
- shadcn/ui的Button没有loading,怎么办?
- 怎么使用safe-server-action?
- Zod应该怎么使用?比如声明了一个结构体,应该怎么赋值呢?
- 怎么实现选择Emoji?
- 发现一个问题useAction的操作是异步的!
- Icon可以选择的网站~
- 如何从结构体中去除某个字段?-Omit
- 遇到一个问题form的值没有更新啊!SetValue
- diaglog里的form数据没有被清空。
- TODO 图片尺寸不对···
- 部署在vercel之后,一直报错Prisma is not defined
- shadcn/ui的Drawer组件在移动端有问题!
背景
在工作学习中,发现一个问题,那就是有一个导航网站非常重要!
无意之中,看到一个很棒的导航网站,打算基于此开发一个,记录一下开发的过程。
Demo仓库:https://github.com/wangfengyuan/frontend-nav
记录
tailwindcss的scrollbar
https://adoxography.github.io/tailwind-scrollbar/examples
prisma的env没有读取到dababase_url
参考这个帖子:
两种解法:
1、安装dotenv
2、直接env.local改名为env
登陆怎么做?
bcrypt-ts到底怎么用?
!!!注意!不能够把加盐的函数直接去比较,因为每次生产的都是不一样的!

- 如果是Github模式
0、参考https://authjs.dev/getting-started/authentication/oauth
1、先在github申请appid和secret,填写url链接
2、而后在nextjs的env中写上

- 如果是账号密码模式
https://authjs.dev/getting-started/authentication/credentials

必须这样!!!官方文档是错的!!

from的action类型错误?
不用管···
https://www.reddit.com/r/nextjs/comments/1616bh9/form_action_not_working/
https://github.com/vercel/next.js/discussions/56581
client和server的调用方式不一样··


客户端的组件又报错了CSRF···

发现是环境变量错了,直接注释掉就行:

shadcn/ui的Button没有loading,怎么办?
直接参考这个文章:https://blog.typeart.cc/add-loading-spinner-in-shadcn-ui-button/
+ import { Loader2 } from 'lucide-react';// ... 略過前面 cva 部份export interface ButtonPropsextends React.ButtonHTMLAttributes<HTMLButtonElement>,VariantProps<typeof buttonVariants> {asChild?: boolean;+ loading?: boolean;}// 將 loading 與 children 從 props 取出來const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(+ ({ className, variant, size, asChild = false, loading, children, ...props }, ref) => {const Comp = asChild ? Slot : 'button';return (<CompclassName={cn(buttonVariants({ variant, size, className }))}+ disabled={loading}ref={ref}{...props}>+ {loading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : children}</Comp>);},);Button.displayName = 'Button';
怎么使用safe-server-action?
官方文档:https://next-safe-action.dev/
Zod应该怎么使用?比如声明了一个结构体,应该怎么赋值呢?
官方文档:https://zod.dev/?id=basic-usage
这样:
import { z } from "zod";const User = z.object({username: z.string(),});User.parse({ username: "Ludwig" });// extract the inferred typetype User = z.infer<typeof User>;// { username: string }
怎么实现选择Emoji?

如上图,我需要在这个输入框,可以选择表情或者分组地址。
找到一个库,在这里:https://ealush.com/emoji-picker-react/
很好用,可以选择屏蔽某些不需要的Emoji,比如Flag····
当选择表情之后,会有一个callBack,输出的内容是当前的表情信息:
{"activeSkinTone": "neutral","emoji": "😆","imageUrl": "https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/1f606.png","isCustom": false,"names": ["laughing","satisfied","smiling face with open mouth and tightly-closed eyes"],"unified": "1f606","unifiedWithoutSkinTone": "1f606"}
发现一个问题useAction的操作是异步的!
// 调用Action进行更新const AddCategoryAction = useAction(AddCategory)<Buttontype="submit"variant="default"loading={AddCategoryAction.isPending}onClick={async () => {await AddCategoryAction.execute(newCategory)mylog("AddCategoryAction res", AddCategoryAction.result)if (AddCategoryAction.hasErrored) {mylog("AddCategory Err",AddCategoryAction.result.validationErrors)toast(JSON.stringify(AddCategoryAction.result.validationErrors) ??"分类添加失败,请重试")} else {toast("分类添加成功")// window.location.reload()}}}>保存</Button>
由于是hook来的,在onclick函数里是异步的,造成数据不一致,怎么办啊!
两种方法:
1、换成使用const res = await AddCategoryAction.executeAsync(newCategory)
2、使用useEffect来监听
useEffect(() => {if (!AddCategoryAction.isPending) {if (AddCategoryAction.hasErrored) {toast(JSON.stringify(AddCategoryAction.result.validationErrors) ??"分类添加失败,请重试")} else {toast("分类添加成功")// 你可以在这里执行其他操作,比如关闭对话框或重置表单}}}, [AddCategoryAction.isPending,AddCategoryAction.hasErrored,AddCategoryAction.result,])
Icon可以选择的网站~
https://lucide.dev/guide/packages/lucide-react
如何从结构体中去除某个字段?-Omit
在 TypeScript 中没有严格意义上的“结构体”概念,但可以通过对象类型或接口来模拟。要从一个对象中去除某个字段,可以通过类型断言和对象解构的方式来实现。
假设你有一个类型如下:
interface MyType {field1: string;field2: number;field3: boolean;}
现在要去除 field2 字段,可以这样做:
const obj: MyType = { field1: 'some string', field2: 123, field3: true };const { field2,...rest } = obj;const newObj = rest as Omit<MyType, 'field2'>;console.log(newObj);
这里使用了对象解构和类型断言来创建一个新的对象,不包含指定的字段。
或者可以使用 Omit 类型工具来创建一个新的类型,然后将原对象转换为新类型:
type NewType = Omit<MyType, 'field2'>;const newObj2: NewType = obj as NewType;console.log(newObj2);
遇到一个问题form的值没有更新啊!SetValue
有一个issue已经提到了:https://github.com/react-hook-form/react-hook-form/issues/456
其实关键在于SetValue不会导致form的组件重新更新。
如果想实现setValue之后,组件内容更新,需要useEffect进行组件re-render。
diaglog里的form数据没有被清空。
发现新建一个分类之后,再次点开新建,里面的内容还是上一次保存的数据,因此需要做一次清空。

TODO 图片尺寸不对···

源代码如下:

到底什么原因呢?
部署在vercel之后,一直报错Prisma is not defined
谷歌了半天,一直没找到问题出在哪··
发现是没有import····为什么编辑器没有提示啊?

shadcn/ui的Drawer组件在移动端有问题!
会导致移动端输入、下滑出现问题。
直接换成Sheet组件即可!
