- 背景
- 记录
- 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 ButtonProps
extends 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 (
<Comp
className={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 type
type 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)
<Button
type="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组件即可!