From dbf55f23ea5d44145b75c28617f8c83d96bb3f3e Mon Sep 17 00:00:00 2001 From: Wisdom Date: Fri, 17 Jan 2025 16:46:58 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=B9=20refactor:=20upgrade=20forwardRef?= =?UTF-8?q?=20to=20useRef=20for=20React=20v19?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 +-- eslint.config.js | 2 + src/components/HomepageHero/Setup.tsx | 20 +++- .../HomepageHero/SetupHero.module.scss | 6 -- src/components/ui/accordion.tsx | 101 ++++++++++-------- src/components/ui/alert.tsx | 74 +++++++------ src/components/ui/button.tsx | 30 +++--- src/components/ui/hover-card.tsx | 31 +++--- src/components/ui/separator.tsx | 25 +++-- src/components/ui/toggle.tsx | 27 +++-- src/i18n/en.ts | 2 + src/i18n/zh.ts | 1 + tailwind.config.ts | 16 ++- tsconfig.json | 4 +- 14 files changed, 207 insertions(+), 145 deletions(-) diff --git a/README.md b/README.md index dd65056..a0fa079 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![thanks](https://badgen.net/badge/thanks/♥/pink)](https://github.com/pdsuwwz) [![License](https://img.shields.io/github/license/pdsuwwz/nextjs-nextra-starter?color=466fe8)](https://github.com/pdsuwwz/nextjs-nextra-starter/blob/main/LICENSE) -⚡️ 快速模板 Starter Template - Next.js + Nextra + TypeScript + TailwindCSS + Shadcn UI +⚡️ 快速模板 Starter Template - React v19 + Next.js + Nextra + TypeScript + TailwindCSS + Shadcn UI [🚀 Live Demo 在线体验](https://nextjs-nextra-starter-green.vercel.app) @@ -20,7 +20,7 @@ ## 前置条件 -- React 18.x +- React 19.x - Node >= 18.12.x - Pnpm 9.x - **VS Code 插件 `dbaeumer.vscode-eslint` >= v3.0.5 (pre-release)** @@ -31,8 +31,6 @@ ![image](https://github.com/user-attachments/assets/7f4ade20-8364-4e25-a5fd-73e42ec7118c) ![image](https://github.com/user-attachments/assets/a0a07f3f-a457-4521-a45f-4c0f970044f6) - - ## 安装和运行 - 安装依赖 @@ -53,7 +51,7 @@ pnpm dev ### Shadcn 结构初始化 -首次执行 `pnpm dlx shadcn-ui@latest init` 命令初始化 `Shadcn UI` 基本项目结构(如果尚未初始化) +首次执行 `pnpm dlx shadcn@latest init` 命令初始化 `Shadcn UI` 基本项目结构(如果尚未初始化) 💡 注意 @@ -66,13 +64,13 @@ pnpm dev 1. 使用 `Shadcn CLI` 添加组件: ```bash - pnpm dlx shadcn-ui@latest add <组件名> + pnpm dlx shadcn@latest add <组件名> ``` 如添加 `` 组件,执行以下命令即可,[详见文档](https://ui.shadcn.com/docs/components/alert#installation) ```bash - pnpm dlx shadcn-ui@latest add alert + pnpm dlx shadcn@latest add alert ``` 2. 使用组件 @@ -88,7 +86,6 @@ export default function Home() { You can add components and dependencies to your app using the cli. - ) } ``` diff --git a/eslint.config.js b/eslint.config.js index 17b1a72..7ea5906 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -40,6 +40,8 @@ export default antfu({ 'react/no-useless-fragment': OFF, 'react/no-array-index-key': OFF, 'react-hooks/rules-of-hooks': OFF, + 'react-refresh/only-export-components': OFF, + 'react-dom/no-dangerously-set-innerhtml': OFF, 'unused-imports/no-unused-vars': WARN, curly: [ERROR, 'multi-line', 'consistent'], diff --git a/src/components/HomepageHero/Setup.tsx b/src/components/HomepageHero/Setup.tsx index 4d06d5c..4b5ae79 100644 --- a/src/components/HomepageHero/Setup.tsx +++ b/src/components/HomepageHero/Setup.tsx @@ -4,6 +4,7 @@ import { Button } from '@/components/ui/button' import { FlipWords } from '@/components/ui/flip-words' import { LinkPreview } from '@/components/ui/link-preview' import { useLocale } from '@/hooks' +import clsx from 'clsx' import Link from 'next/link' interface Props { @@ -13,7 +14,6 @@ export function SetupHero(props: Props) { return (
- {/*
*/}
+ +

span]:font-bold', + 'animate-pulse', + '[animation-duration:2s]', + ])} + dangerouslySetInnerHTML={{ + __html: t('reactSupport', { + feature: `React v19`, + }), + }} + /> + +

Template made {' '} diff --git a/src/components/HomepageHero/SetupHero.module.scss b/src/components/HomepageHero/SetupHero.module.scss index 02158f8..45e1486 100644 --- a/src/components/HomepageHero/SetupHero.module.scss +++ b/src/components/HomepageHero/SetupHero.module.scss @@ -2,12 +2,6 @@ position: relative; } -.tilesBox { - position: absolute; - width: 100%; - height: 100%; -} - .content { margin: 0 auto; position: relative; diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx index 7babbb6..1a0df67 100644 --- a/src/components/ui/accordion.tsx +++ b/src/components/ui/accordion.tsx @@ -6,57 +6,70 @@ import * as React from 'react' const Accordion = AccordionPrimitive.Root -const AccordionItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AccordionItem.displayName = 'AccordionItem' +const AccordionItem = ({ + className, + ...props +}: React.ComponentPropsWithoutRef) => { + const itemRef = React.useRef>(null) -const AccordionTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - svg]:rotate-180', - 'text-[18px] font-bold', + 'border-b', className, )} {...props} - > - {children} - - - -)) + /> + ) +} +AccordionItem.displayName = 'AccordionItem' + +const AccordionTrigger = ({ + className, + children, + ...props +}: React.ComponentPropsWithoutRef) => { + const itemRef = React.useRef>(null) + return ( + + svg]:rotate-180', + 'text-[18px] font-bold', + className, + )} + {...props} + > + {children} + + + + ) +} AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName -const AccordionContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - -
{children}
-
-)) +const AccordionContent = ({ + className, + children, + ...props +}: React.ComponentPropsWithoutRef) => { + const itemRef = React.useRef>(null) + + return ( + +
{children}
+
+ ) +} AccordionContent.displayName = AccordionPrimitive.Content.displayName diff --git a/src/components/ui/alert.tsx b/src/components/ui/alert.tsx index 6085694..63859a0 100644 --- a/src/components/ui/alert.tsx +++ b/src/components/ui/alert.tsx @@ -19,41 +19,53 @@ const alertVariants = cva( }, ) -const Alert = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes & VariantProps ->(({ className, variant, ...props }, ref) => ( -
-)) +const Alert = ({ + className, + variant, + ...props +}: React.HTMLAttributes & VariantProps) => { + const itemRef = React.useRef(null) + return ( +
+ ) +} Alert.displayName = 'Alert' -const AlertTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) +const AlertTitle = ({ + className, + ...props +}: React.HTMLAttributes) => { + const itemRef = React.useRef(null) + + return ( +
+ ) +} AlertTitle.displayName = 'AlertTitle' -const AlertDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) +const AlertDescription = ({ + className, + ...props +}: React.HTMLAttributes) => { + const itemRef = React.useRef(null) + + return ( +
+ ) +} AlertDescription.displayName = 'AlertDescription' export { Alert, AlertDescription, AlertTitle } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 7b38509..1a81183 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -39,18 +39,24 @@ export interface ButtonProps asChild?: boolean } -const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : 'button' - return ( - - ) - }, -) +const Button = ({ + className, + variant, + size, + asChild = false, + ...props +}: ButtonProps) => { + const Comp = asChild ? Slot : 'button' + const itemRef = React.useRef(null) + + return ( + + ) +} Button.displayName = 'Button' export { Button, buttonVariants } diff --git a/src/components/ui/hover-card.tsx b/src/components/ui/hover-card.tsx index d958964..b82fca9 100644 --- a/src/components/ui/hover-card.tsx +++ b/src/components/ui/hover-card.tsx @@ -9,21 +9,22 @@ const HoverCard = HoverCardPrimitive.Root const HoverCardTrigger = HoverCardPrimitive.Trigger -const HoverCardContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, align = 'center', sideOffset = 4, ...props }, ref) => ( - -)) + +const HoverCardContent = ({ className, align = 'center', sideOffset = 4, ...props }: React.ComponentPropsWithoutRef) => { + const itemRef = React.useRef>(null) + return ( + + ) +} HoverCardContent.displayName = HoverCardPrimitive.Content.displayName export { HoverCard, HoverCardContent, HoverCardTrigger } diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx index d5b600f..94e7b8b 100644 --- a/src/components/ui/separator.tsx +++ b/src/components/ui/separator.tsx @@ -3,16 +3,19 @@ import * as SeparatorPrimitive from '@radix-ui/react-separator' import * as React from 'react' -const Separator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->( - ( - { className, orientation = 'horizontal', decorative = true, ...props }, - ref, - ) => ( +const Separator = ( + { + className, + orientation = 'horizontal', + decorative = true, + ...props + }: React.ComponentPropsWithoutRef, +) => { + const itemRef = React.useRef>(null) + + return ( - ), -) + ) +} Separator.displayName = SeparatorPrimitive.Root.displayName export { Separator } diff --git a/src/components/ui/toggle.tsx b/src/components/ui/toggle.tsx index b529dec..3e472d2 100644 --- a/src/components/ui/toggle.tsx +++ b/src/components/ui/toggle.tsx @@ -26,17 +26,22 @@ const toggleVariants = cva( }, ) -const Toggle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & - VariantProps ->(({ className, variant, size, ...props }, ref) => ( - -)) +const Toggle = ({ + className, + variant, + size, + ...props +}: React.ComponentPropsWithoutRef & VariantProps) => { + const itemRef = React.useRef>(null) + + return ( + + ) +} Toggle.displayName = TogglePrimitive.Root.displayName diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 5d3b81e..f29a45a 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -7,6 +7,8 @@ export default { badgeTitle: 'Lightweight & Easy 🎉', + reactSupport: `🔥 Now with {{feature}} support!`, + featureList: [ { title: 'Advanced Tech Stack', diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts index a464fd8..d94f68e 100644 --- a/src/i18n/zh.ts +++ b/src/i18n/zh.ts @@ -6,6 +6,7 @@ export default { }, badgeTitle: '轻量级、开箱即用 🎉', + reactSupport: `🔥 现在支持 {{feature}}!`, featureList: [ { diff --git a/tailwind.config.ts b/tailwind.config.ts index 3ddd9e3..404db18 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -63,12 +63,20 @@ const config = { }, keyframes: { 'accordion-down': { - from: { height: '0' }, - to: { height: 'var(--radix-accordion-content-height)' }, + from: { + height: '0', + }, + to: { + height: 'var(--radix-accordion-content-height)', + }, }, 'accordion-up': { - from: { height: 'var(--radix-accordion-content-height)' }, - to: { height: '0' }, + from: { + height: 'var(--radix-accordion-content-height)', + }, + to: { + height: '0', + }, }, }, animation: { diff --git a/tsconfig.json b/tsconfig.json index bbe688e..8298cd8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "incremental": true, + "target": "ES2017", "jsx": "preserve", "lib": [ "dom", @@ -26,8 +27,7 @@ { "name": "next" } - ], - "target": "ES2017" + ] }, "include": [ "next-env.d.ts",