@ngxtm/devkit 3.4.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/rules/README.md +141 -0
- package/rules/dart/best-practices/SKILL.md +23 -0
- package/rules/dart/language/SKILL.md +52 -0
- package/rules/dart/tooling/SKILL.md +43 -0
- package/rules/dotnet/aspnet-core/SKILL.md +92 -0
- package/rules/dotnet/aspnet-core/references/REFERENCE.md +335 -0
- package/rules/dotnet/best-practices/SKILL.md +101 -0
- package/rules/dotnet/best-practices/references/REFERENCE.md +256 -0
- package/rules/dotnet/blazor/SKILL.md +146 -0
- package/rules/dotnet/blazor/references/REFERENCE.md +392 -0
- package/rules/dotnet/language/SKILL.md +82 -0
- package/rules/dotnet/language/references/REFERENCE.md +222 -0
- package/rules/dotnet/patterns.rule.md +388 -0
- package/rules/dotnet/razor-pages/SKILL.md +124 -0
- package/rules/dotnet/razor-pages/references/REFERENCE.md +321 -0
- package/rules/dotnet/security/SKILL.md +89 -0
- package/rules/dotnet/security/references/REFERENCE.md +295 -0
- package/rules/dotnet/tooling/SKILL.md +92 -0
- package/rules/dotnet/tooling/references/REFERENCE.md +300 -0
- package/rules/flutter/auto-route-navigation/SKILL.md +43 -0
- package/rules/flutter/auto-route-navigation/references/REFERENCE.md +19 -0
- package/rules/flutter/auto-route-navigation/references/router-config.md +62 -0
- package/rules/flutter/bloc-state-management/SKILL.md +64 -0
- package/rules/flutter/bloc-state-management/references/REFERENCE.md +20 -0
- package/rules/flutter/bloc-state-management/references/auth-bloc-example.md +52 -0
- package/rules/flutter/bloc-state-management/references/equatable-usage.md +56 -0
- package/rules/flutter/bloc-state-management/references/property-based-state.md +68 -0
- package/rules/flutter/bloc.rule.md +76 -0
- package/rules/flutter/cicd/SKILL.md +48 -0
- package/rules/flutter/cicd/references/advanced-workflow.md +66 -0
- package/rules/flutter/cicd/references/fastlane.md +139 -0
- package/rules/flutter/cicd/references/github-actions.md +59 -0
- package/rules/flutter/dependency-injection/SKILL.md +42 -0
- package/rules/flutter/dependency-injection/references/REFERENCE.md +15 -0
- package/rules/flutter/dependency-injection/references/modules.md +37 -0
- package/rules/flutter/error-handling/SKILL.md +32 -0
- package/rules/flutter/error-handling/references/REFERENCE.md +19 -0
- package/rules/flutter/error-handling/references/error-mapping.md +31 -0
- package/rules/flutter/feature-based-clean-architecture/SKILL.md +46 -0
- package/rules/flutter/feature-based-clean-architecture/references/REFERENCE.md +14 -0
- package/rules/flutter/feature-based-clean-architecture/references/folder-structure.md +36 -0
- package/rules/flutter/getx-navigation/SKILL.md +70 -0
- package/rules/flutter/getx-navigation/references/app-pages.md +40 -0
- package/rules/flutter/getx-navigation/references/middleware-example.md +29 -0
- package/rules/flutter/getx-state-management/SKILL.md +76 -0
- package/rules/flutter/getx-state-management/references/binding-example.md +32 -0
- package/rules/flutter/getx-state-management/references/reactive-vs-simple.md +39 -0
- package/rules/flutter/go-router-navigation/SKILL.md +57 -0
- package/rules/flutter/idiomatic-flutter/SKILL.md +20 -0
- package/rules/flutter/layer-based-clean-architecture/SKILL.md +50 -0
- package/rules/flutter/layer-based-clean-architecture/references/REFERENCE.md +60 -0
- package/rules/flutter/layer-based-clean-architecture/references/repository-mapping.md +50 -0
- package/rules/flutter/localization/SKILL.md +50 -0
- package/rules/flutter/localization/references/REFERENCE.md +48 -0
- package/rules/flutter/localization/references/sheet-loader.md +33 -0
- package/rules/flutter/navigator-v1-navigation/SKILL.md +71 -0
- package/rules/flutter/navigator-v1-navigation/references/on-generate-route.md +48 -0
- package/rules/flutter/performance/SKILL.md +24 -0
- package/rules/flutter/retrofit-networking/SKILL.md +51 -0
- package/rules/flutter/retrofit-networking/references/REFERENCE.md +19 -0
- package/rules/flutter/retrofit-networking/references/token-refresh.md +40 -0
- package/rules/flutter/riverpod-state-management/SKILL.md +53 -0
- package/rules/flutter/riverpod-state-management/references/architecture.md +124 -0
- package/rules/flutter/riverpod-state-management/references/best-practices.md +89 -0
- package/rules/flutter/riverpod-state-management/references/testing.md +73 -0
- package/rules/flutter/riverpod.rule.md +78 -0
- package/rules/flutter/security/SKILL.md +33 -0
- package/rules/flutter/security/references/REFERENCE.md +15 -0
- package/rules/flutter/security/references/network-security.md +28 -0
- package/rules/flutter/testing/SKILL.md +44 -0
- package/rules/flutter/testing/references/REFERENCE.md +21 -0
- package/rules/flutter/testing/references/bloc-testing.md +38 -0
- package/rules/flutter/testing/references/integration-testing.md +128 -0
- package/rules/flutter/testing/references/robot-pattern.md +82 -0
- package/rules/flutter/testing/references/unit-testing.md +130 -0
- package/rules/flutter/testing/references/widget-testing.md +120 -0
- package/rules/flutter/widgets/SKILL.md +37 -0
- package/rules/golang/chi-router/SKILL.md +219 -0
- package/rules/golang/chi-router/references/REFERENCE.md +13 -0
- package/rules/golang/chi-router/references/routing-patterns.md +205 -0
- package/rules/golang/cobra-cli/SKILL.md +227 -0
- package/rules/golang/cobra-cli/references/REFERENCE.md +13 -0
- package/rules/golang/cobra-cli/references/command-patterns.md +224 -0
- package/rules/golang/core/SKILL.md +210 -0
- package/rules/golang/core/references/REFERENCE.md +14 -0
- package/rules/golang/core/references/concurrency-patterns.md +114 -0
- package/rules/golang/core/references/error-handling.md +87 -0
- package/rules/golang/echo-framework/SKILL.md +215 -0
- package/rules/golang/echo-framework/references/REFERENCE.md +14 -0
- package/rules/golang/echo-framework/references/middleware-patterns.md +141 -0
- package/rules/golang/echo-framework/references/routing-patterns.md +140 -0
- package/rules/golang/ent-orm/SKILL.md +239 -0
- package/rules/golang/ent-orm/references/REFERENCE.md +13 -0
- package/rules/golang/ent-orm/references/schema-patterns.md +255 -0
- package/rules/golang/fiber-framework/SKILL.md +196 -0
- package/rules/golang/fiber-framework/references/REFERENCE.md +13 -0
- package/rules/golang/fiber-framework/references/routing-patterns.md +191 -0
- package/rules/golang/gin-framework/SKILL.md +205 -0
- package/rules/golang/gin-framework/references/REFERENCE.md +14 -0
- package/rules/golang/gin-framework/references/middleware-patterns.md +119 -0
- package/rules/golang/gorm-orm/SKILL.md +196 -0
- package/rules/golang/gorm-orm/references/REFERENCE.md +14 -0
- package/rules/golang/gorm-orm/references/model-definitions.md +167 -0
- package/rules/golang/gorm-orm/references/query-patterns.md +161 -0
- package/rules/golang/grpc/SKILL.md +231 -0
- package/rules/golang/grpc/references/REFERENCE.md +13 -0
- package/rules/golang/grpc/references/service-patterns.md +276 -0
- package/rules/golang/testify/SKILL.md +239 -0
- package/rules/golang/testify/references/REFERENCE.md +13 -0
- package/rules/golang/testify/references/assert-patterns.md +170 -0
- package/rules/golang/validator/SKILL.md +234 -0
- package/rules/golang/validator/references/REFERENCE.md +13 -0
- package/rules/golang/validator/references/validation-tags.md +211 -0
- package/rules/golang/viper-config/SKILL.md +244 -0
- package/rules/golang/viper-config/references/REFERENCE.md +13 -0
- package/rules/golang/viper-config/references/config-loading.md +181 -0
- package/rules/golang/wire-di/SKILL.md +243 -0
- package/rules/golang/wire-di/references/REFERENCE.md +13 -0
- package/rules/golang/wire-di/references/provider-patterns.md +193 -0
- package/rules/golang/zap-logging/SKILL.md +203 -0
- package/rules/golang/zap-logging/references/REFERENCE.md +13 -0
- package/rules/golang/zap-logging/references/logger-config.md +165 -0
- package/rules/java/build-gradle/SKILL.md +92 -0
- package/rules/java/build-gradle/references/REFERENCE.md +14 -0
- package/rules/java/build-gradle/references/kotlin-dsl.md +118 -0
- package/rules/java/build-gradle/references/task-configuration.md +132 -0
- package/rules/java/build-maven/SKILL.md +86 -0
- package/rules/java/build-maven/references/REFERENCE.md +14 -0
- package/rules/java/build-maven/references/dependency-management.md +111 -0
- package/rules/java/build-maven/references/lifecycle-phases.md +114 -0
- package/rules/java/graalvm-native/SKILL.md +105 -0
- package/rules/java/graalvm-native/references/REFERENCE.md +12 -0
- package/rules/java/java-collections-streams/SKILL.md +148 -0
- package/rules/java/java-collections-streams/references/REFERENCE.md +15 -0
- package/rules/java/java-collections-streams/references/collectors-patterns.md +178 -0
- package/rules/java/java-collections-streams/references/stream-pipelines.md +165 -0
- package/rules/java/java-concurrency/SKILL.md +187 -0
- package/rules/java/java-concurrency/references/REFERENCE.md +17 -0
- package/rules/java/java-concurrency/references/completable-future.md +165 -0
- package/rules/java/java-concurrency/references/executor-patterns.md +176 -0
- package/rules/java/java-concurrency/references/virtual-threads.md +190 -0
- package/rules/java/java-core-language/SKILL.md +121 -0
- package/rules/java/java-core-language/references/REFERENCE.md +15 -0
- package/rules/java/java-core-language/references/jvm-memory-model.md +160 -0
- package/rules/java/java-core-language/references/modern-java-features.md +168 -0
- package/rules/java/java-project-structure/SKILL.md +195 -0
- package/rules/java/java-project-structure/references/REFERENCE.md +15 -0
- package/rules/java/java-project-structure/references/maven-project-layout.md +199 -0
- package/rules/java/java-project-structure/references/module-system.md +159 -0
- package/rules/java/micronaut-core/SKILL.md +99 -0
- package/rules/java/micronaut-core/references/REFERENCE.md +12 -0
- package/rules/java/micronaut-reactive/SKILL.md +68 -0
- package/rules/java/micronaut-reactive/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-core/SKILL.md +85 -0
- package/rules/java/quarkus-core/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-reactive/SKILL.md +67 -0
- package/rules/java/quarkus-reactive/references/REFERENCE.md +12 -0
- package/rules/java/spring-batch/SKILL.md +102 -0
- package/rules/java/spring-batch/references/REFERENCE.md +12 -0
- package/rules/java/spring-boot-architecture/SKILL.md +206 -0
- package/rules/java/spring-boot-architecture/references/REFERENCE.md +15 -0
- package/rules/java/spring-boot-architecture/references/auto-configuration.md +158 -0
- package/rules/java/spring-boot-architecture/references/configuration-properties.md +202 -0
- package/rules/java/spring-boot-web/SKILL.md +217 -0
- package/rules/java/spring-boot-web/references/REFERENCE.md +17 -0
- package/rules/java/spring-cloud/SKILL.md +109 -0
- package/rules/java/spring-cloud/references/REFERENCE.md +13 -0
- package/rules/java/spring-data-jpa/SKILL.md +241 -0
- package/rules/java/spring-data-jpa/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/SKILL.md +161 -0
- package/rules/java/spring-security/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/references/jwt-auth-flow.md +213 -0
- package/rules/java/testing-junit-mockito/SKILL.md +135 -0
- package/rules/java/testing-junit-mockito/references/REFERENCE.md +15 -0
- package/rules/java/testing-junit-mockito/references/junit5-patterns.md +159 -0
- package/rules/java/testing-junit-mockito/references/mockito-patterns.md +148 -0
- package/rules/java/testing-junit-mockito/references/spring-boot-testing.md +152 -0
- package/rules/javascript/best-practices/SKILL.md +64 -0
- package/rules/javascript/best-practices/references/REFERENCE.md +91 -0
- package/rules/javascript/language/SKILL.md +71 -0
- package/rules/javascript/language/references/REFERENCE.md +106 -0
- package/rules/javascript/tooling/SKILL.md +60 -0
- package/rules/javascript/tooling/references/REFERENCE.md +107 -0
- package/rules/metadata.json +54 -0
- package/rules/nestjs/api-standards/SKILL.md +47 -0
- package/rules/nestjs/api-standards/references/pagination-wrapper.md +87 -0
- package/rules/nestjs/architecture/SKILL.md +68 -0
- package/rules/nestjs/architecture/references/dynamic-module.md +53 -0
- package/rules/nestjs/caching/SKILL.md +51 -0
- package/rules/nestjs/caching/references/REFERENCE.md +13 -0
- package/rules/nestjs/caching/references/cache-patterns.md +183 -0
- package/rules/nestjs/configuration/SKILL.md +41 -0
- package/rules/nestjs/configuration/references/REFERENCE.md +13 -0
- package/rules/nestjs/configuration/references/config-patterns.md +184 -0
- package/rules/nestjs/controllers-services/SKILL.md +63 -0
- package/rules/nestjs/controllers-services/references/REFERENCE.md +14 -0
- package/rules/nestjs/controllers-services/references/controller-patterns.md +119 -0
- package/rules/nestjs/controllers-services/references/service-patterns.md +129 -0
- package/rules/nestjs/database/SKILL.md +102 -0
- package/rules/nestjs/database/references/REFERENCE.md +14 -0
- package/rules/nestjs/database/references/typeorm-patterns.md +156 -0
- package/rules/nestjs/deployment/SKILL.md +36 -0
- package/rules/nestjs/deployment/references/REFERENCE.md +13 -0
- package/rules/nestjs/deployment/references/deployment-patterns.md +140 -0
- package/rules/nestjs/documentation/SKILL.md +64 -0
- package/rules/nestjs/documentation/references/REFERENCE.md +13 -0
- package/rules/nestjs/documentation/references/swagger-patterns.md +139 -0
- package/rules/nestjs/error-handling/SKILL.md +55 -0
- package/rules/nestjs/error-handling/references/REFERENCE.md +13 -0
- package/rules/nestjs/error-handling/references/exception-filters.md +152 -0
- package/rules/nestjs/file-uploads/SKILL.md +35 -0
- package/rules/nestjs/file-uploads/references/REFERENCE.md +13 -0
- package/rules/nestjs/file-uploads/references/upload-patterns.md +125 -0
- package/rules/nestjs/observability/SKILL.md +39 -0
- package/rules/nestjs/observability/references/REFERENCE.md +13 -0
- package/rules/nestjs/observability/references/logging-metrics.md +175 -0
- package/rules/nestjs/performance/SKILL.md +60 -0
- package/rules/nestjs/performance/references/REFERENCE.md +13 -0
- package/rules/nestjs/performance/references/performance-patterns.md +107 -0
- package/rules/nestjs/real-time/SKILL.md +45 -0
- package/rules/nestjs/real-time/references/REFERENCE.md +13 -0
- package/rules/nestjs/real-time/references/websocket-patterns.md +121 -0
- package/rules/nestjs/scheduling/SKILL.md +39 -0
- package/rules/nestjs/scheduling/references/REFERENCE.md +13 -0
- package/rules/nestjs/scheduling/references/scheduling-patterns.md +137 -0
- package/rules/nestjs/search/SKILL.md +41 -0
- package/rules/nestjs/search/references/REFERENCE.md +13 -0
- package/rules/nestjs/search/references/search-patterns.md +137 -0
- package/rules/nestjs/security/SKILL.md +87 -0
- package/rules/nestjs/security/references/REFERENCE.md +14 -0
- package/rules/nestjs/security/references/authentication.md +151 -0
- package/rules/nestjs/testing/SKILL.md +40 -0
- package/rules/nestjs/testing/references/REFERENCE.md +14 -0
- package/rules/nestjs/testing/references/unit-testing.md +179 -0
- package/rules/nestjs/transport/SKILL.md +45 -0
- package/rules/nestjs/transport/references/REFERENCE.md +13 -0
- package/rules/nestjs/transport/references/microservices-patterns.md +170 -0
- package/rules/nextjs/app-router/SKILL.md +46 -0
- package/rules/nextjs/app-router/references/REFERENCE.md +14 -0
- package/rules/nextjs/app-router/references/routing-patterns.md +182 -0
- package/rules/nextjs/architecture/SKILL.md +44 -0
- package/rules/nextjs/architecture/references/fsd-structure.md +77 -0
- package/rules/nextjs/authentication/SKILL.md +29 -0
- package/rules/nextjs/authentication/references/auth-implementation.md +73 -0
- package/rules/nextjs/caching/SKILL.md +66 -0
- package/rules/nextjs/caching/references/REFERENCE.md +13 -0
- package/rules/nextjs/caching/references/cache-strategies.md +168 -0
- package/rules/nextjs/data-access-layer/SKILL.md +33 -0
- package/rules/nextjs/data-access-layer/references/patterns.md +66 -0
- package/rules/nextjs/data-fetching/SKILL.md +59 -0
- package/rules/nextjs/data-fetching/references/REFERENCE.md +13 -0
- package/rules/nextjs/data-fetching/references/fetch-patterns.md +160 -0
- package/rules/nextjs/internationalization/SKILL.md +105 -0
- package/rules/nextjs/internationalization/references/REFERENCE.md +13 -0
- package/rules/nextjs/internationalization/references/i18n-patterns.md +180 -0
- package/rules/nextjs/optimization/SKILL.md +64 -0
- package/rules/nextjs/optimization/references/REFERENCE.md +13 -0
- package/rules/nextjs/optimization/references/optimization-patterns.md +190 -0
- package/rules/nextjs/rendering/SKILL.md +91 -0
- package/rules/nextjs/rendering/references/REFERENCE.md +13 -0
- package/rules/nextjs/rendering/references/rendering-modes.md +163 -0
- package/rules/nextjs/server-actions/SKILL.md +46 -0
- package/rules/nextjs/server-actions/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-actions/references/action-patterns.md +188 -0
- package/rules/nextjs/server-components/SKILL.md +52 -0
- package/rules/nextjs/server-components/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-components/references/component-patterns.md +175 -0
- package/rules/nextjs/state-management/SKILL.md +73 -0
- package/rules/nextjs/state-management/references/REFERENCE.md +13 -0
- package/rules/nextjs/state-management/references/state-patterns.md +218 -0
- package/rules/nextjs/styling/SKILL.md +31 -0
- package/rules/nextjs/styling/references/implementation.md +56 -0
- package/rules/react/component-patterns/SKILL.md +66 -0
- package/rules/react/component-patterns/references/REFERENCE.md +126 -0
- package/rules/react/hooks/SKILL.md +60 -0
- package/rules/react/hooks/references/REFERENCE.md +132 -0
- package/rules/react/hooks.rule.md +79 -0
- package/rules/react/performance/SKILL.md +69 -0
- package/rules/react/performance/references/REFERENCE.md +143 -0
- package/rules/react/security/SKILL.md +46 -0
- package/rules/react/security/references/REFERENCE.md +170 -0
- package/rules/react/state-management/SKILL.md +56 -0
- package/rules/react/state-management/references/REFERENCE.md +137 -0
- package/rules/react/testing/SKILL.md +45 -0
- package/rules/react/testing/references/REFERENCE.md +149 -0
- package/rules/react/tooling/SKILL.md +39 -0
- package/rules/react/typescript/SKILL.md +53 -0
- package/rules/rust/actix-web/SKILL.md +160 -0
- package/rules/rust/actix-web/references/REFERENCE.md +13 -0
- package/rules/rust/actix-web/references/handler-patterns.md +198 -0
- package/rules/rust/async-graphql/SKILL.md +228 -0
- package/rules/rust/async-graphql/references/REFERENCE.md +13 -0
- package/rules/rust/async-graphql/references/schema-patterns.md +215 -0
- package/rules/rust/axum/SKILL.md +161 -0
- package/rules/rust/axum/references/REFERENCE.md +14 -0
- package/rules/rust/axum/references/handler-patterns.md +97 -0
- package/rules/rust/bevy/SKILL.md +206 -0
- package/rules/rust/bevy/references/REFERENCE.md +13 -0
- package/rules/rust/bevy/references/ecs-patterns.md +226 -0
- package/rules/rust/clap/SKILL.md +217 -0
- package/rules/rust/clap/references/REFERENCE.md +13 -0
- package/rules/rust/clap/references/derive-patterns.md +205 -0
- package/rules/rust/core/SKILL.md +154 -0
- package/rules/rust/core/references/REFERENCE.md +14 -0
- package/rules/rust/core/references/error-handling.md +92 -0
- package/rules/rust/diesel-orm/SKILL.md +176 -0
- package/rules/rust/diesel-orm/references/REFERENCE.md +13 -0
- package/rules/rust/diesel-orm/references/schema-patterns.md +206 -0
- package/rules/rust/rocket/SKILL.md +182 -0
- package/rules/rust/rocket/references/REFERENCE.md +13 -0
- package/rules/rust/rocket/references/handler-patterns.md +209 -0
- package/rules/rust/sea-orm/SKILL.md +230 -0
- package/rules/rust/sea-orm/references/REFERENCE.md +13 -0
- package/rules/rust/sea-orm/references/entity-patterns.md +221 -0
- package/rules/rust/serde-serialization/SKILL.md +150 -0
- package/rules/rust/serde-serialization/references/REFERENCE.md +13 -0
- package/rules/rust/serde-serialization/references/serialization-patterns.md +199 -0
- package/rules/rust/sqlx-database/SKILL.md +140 -0
- package/rules/rust/sqlx-database/references/REFERENCE.md +13 -0
- package/rules/rust/sqlx-database/references/query-patterns.md +210 -0
- package/rules/rust/tauri/SKILL.md +180 -0
- package/rules/rust/tauri/references/REFERENCE.md +13 -0
- package/rules/rust/tauri/references/command-patterns.md +209 -0
- package/rules/rust/tokio-runtime/SKILL.md +167 -0
- package/rules/rust/tokio-runtime/references/REFERENCE.md +14 -0
- package/rules/rust/tokio-runtime/references/async-patterns.md +137 -0
- package/rules/rust/tokio-runtime/references/synchronization.md +152 -0
- package/rules/rust/tonic/SKILL.md +231 -0
- package/rules/rust/tonic/references/REFERENCE.md +13 -0
- package/rules/rust/tonic/references/service-patterns.md +213 -0
- package/rules/rust/tracing/SKILL.md +214 -0
- package/rules/rust/tracing/references/REFERENCE.md +13 -0
- package/rules/rust/tracing/references/instrumentation.md +187 -0
- package/rules/typescript/best-practices/SKILL.md +108 -0
- package/rules/typescript/best-practices/references/REFERENCE.md +68 -0
- package/rules/typescript/language/SKILL.md +72 -0
- package/rules/typescript/language/references/REFERENCE.md +67 -0
- package/rules/typescript/patterns.rule.md +85 -0
- package/rules/typescript/security/SKILL.md +59 -0
- package/rules/typescript/security/references/REFERENCE.md +113 -0
- package/rules/typescript/tooling/SKILL.md +52 -0
- package/rules/typescript/tooling/references/REFERENCE.md +110 -0
- package/skills/learn/SKILL.md +476 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# React Component Patterns Reference
|
|
2
|
+
|
|
3
|
+
Advanced component patterns and composition techniques.
|
|
4
|
+
|
|
5
|
+
## References
|
|
6
|
+
|
|
7
|
+
- [**HOC Pattern**](hoc-pattern.md) - Higher-Order Components.
|
|
8
|
+
- [**Render Props**](render-props.md) - Render prop pattern.
|
|
9
|
+
- [**Compound Components**](compound-components.md) - Complex component composition.
|
|
10
|
+
|
|
11
|
+
## Higher-Order Component (HOC)
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
// withAuth.jsx
|
|
15
|
+
export function withAuth(Component) {
|
|
16
|
+
return function AuthenticatedComponent(props) {
|
|
17
|
+
const { user, loading } = useAuth();
|
|
18
|
+
|
|
19
|
+
if (loading) return <Loading />;
|
|
20
|
+
if (!user) return <Redirect to="/login" />;
|
|
21
|
+
|
|
22
|
+
return <Component {...props} user={user} />;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Usage
|
|
27
|
+
const ProtectedPage = withAuth(Dashboard);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Render Props Pattern
|
|
31
|
+
|
|
32
|
+
```jsx
|
|
33
|
+
// Mouse tracking example
|
|
34
|
+
export function MouseTracker({ render }) {
|
|
35
|
+
const [position, setPosition] = useState({ x: 0, y: 0 });
|
|
36
|
+
|
|
37
|
+
const handleMouseMove = (event) => {
|
|
38
|
+
setPosition({ x: event.clientX, y: event.clientY });
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div onMouseMove={handleMouseMove}>
|
|
43
|
+
{render(position)}
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Usage
|
|
49
|
+
<MouseTracker
|
|
50
|
+
render={({ x, y }) => (
|
|
51
|
+
<p>Mouse position: {x}, {y}</p>
|
|
52
|
+
)}
|
|
53
|
+
/>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Compound Components
|
|
57
|
+
|
|
58
|
+
```jsx
|
|
59
|
+
// Accordion component
|
|
60
|
+
const AccordionContext = createContext();
|
|
61
|
+
|
|
62
|
+
export function Accordion({ children }) {
|
|
63
|
+
const [activeIndex, setActiveIndex] = useState(null);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<AccordionContext.Provider value={{ activeIndex, setActiveIndex }}>
|
|
67
|
+
<div className="accordion">{children}</div>
|
|
68
|
+
</AccordionContext.Provider>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Accordion.Item = function AccordionItem({ index, children }) {
|
|
73
|
+
return <div className="accordion-item">{children}</div>;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
Accordion.Header = function AccordionHeader({ index, children }) {
|
|
77
|
+
const { activeIndex, setActiveIndex } = useContext(AccordionContext);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<button onClick={() => setActiveIndex(index === activeIndex ? null : index)}>
|
|
81
|
+
{children}
|
|
82
|
+
</button>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
Accordion.Body = function AccordionBody({ index, children }) {
|
|
87
|
+
const { activeIndex } = useContext(AccordionContext);
|
|
88
|
+
|
|
89
|
+
return activeIndex === index ? <div>{children}</div> : null;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Usage
|
|
93
|
+
<Accordion>
|
|
94
|
+
<Accordion.Item index={0}>
|
|
95
|
+
<Accordion.Header index={0}>Section 1</Accordion.Header>
|
|
96
|
+
<Accordion.Body index={0}>Content 1</Accordion.Body>
|
|
97
|
+
</Accordion.Item>
|
|
98
|
+
</Accordion>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Controlled vs Uncontrolled
|
|
102
|
+
|
|
103
|
+
```jsx
|
|
104
|
+
// Controlled input
|
|
105
|
+
function ControlledInput() {
|
|
106
|
+
const [value, setValue] = useState('');
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<input
|
|
110
|
+
value={value}
|
|
111
|
+
onChange={e => setValue(e.target.value)}
|
|
112
|
+
/>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Uncontrolled input
|
|
117
|
+
function UncontrolledInput() {
|
|
118
|
+
const inputRef = useRef();
|
|
119
|
+
|
|
120
|
+
const handleSubmit = () => {
|
|
121
|
+
console.log(inputRef.current.value);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return <input ref={inputRef} />;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: React Hooks
|
|
3
|
+
description: Best practices for React Hooks usage and custom hook creation.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [react, hooks, custom-hooks, useeffect]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.tsx', '**/*.jsx']
|
|
8
|
+
keywords: [useEffect, useCallback, useMemo, useRef, custom hook]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# React Hooks
|
|
12
|
+
|
|
13
|
+
## **Priority: P1 (OPERATIONAL)**
|
|
14
|
+
|
|
15
|
+
Effective usage of React Hooks.
|
|
16
|
+
|
|
17
|
+
## Implementation Guidelines
|
|
18
|
+
|
|
19
|
+
- **Rules**: Top-level only. Only in React functions.
|
|
20
|
+
- **`useEffect`**: Sync with external systems ONLY. Cleanup required.
|
|
21
|
+
- **`useRef`**: Mutable state without re-renders (DOM, timers, tracking).
|
|
22
|
+
- **`useMemo`/`Callback`**: Measure first. Use for stable refs or heavy computation.
|
|
23
|
+
- **Dependencies**: Exhaustive deps always. Fix logic, don't disable linter.
|
|
24
|
+
- **Custom Hooks**: Extract shared logic. Prefix `use*`.
|
|
25
|
+
- **Refs as Escape Hatch**: Access imperative APIs (focus, scroll).
|
|
26
|
+
- **Stability**: Use `useLatest` pattern (ref) for event handlers to avoid dependency changes.
|
|
27
|
+
- **Concurrency**: `useTransition` / `useDeferredValue` for non-blocking UI updates.
|
|
28
|
+
- **Initialization**: Lazy state `useState(() => expensive())`.
|
|
29
|
+
|
|
30
|
+
## Anti-Patterns
|
|
31
|
+
|
|
32
|
+
- **No Effects for Data Flow**: Derive state in render.
|
|
33
|
+
- **No Missing Deps**: Causes stale closures.
|
|
34
|
+
- **No Complex Effects**: Split into multiple simple effects.
|
|
35
|
+
- **No Oversubscription**: Check `why-did-you-render`.
|
|
36
|
+
|
|
37
|
+
## Code
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
// Custom Hook
|
|
41
|
+
function useWindowSize() {
|
|
42
|
+
const [size, setSize] = useState({ w: 0, h: 0 });
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const onResize = () =>
|
|
46
|
+
setSize({ w: window.innerWidth, h: window.innerHeight });
|
|
47
|
+
window.addEventListener('resize', onResize);
|
|
48
|
+
return () => window.removeEventListener('resize', onResize);
|
|
49
|
+
}, []); // Empty = mount only
|
|
50
|
+
|
|
51
|
+
return size;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Lazy Init
|
|
55
|
+
const [state, setState] = useState(() => computeExpensiveValue());
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Reference & Examples
|
|
59
|
+
|
|
60
|
+
See [references/REFERENCE.md](references/REFERENCE.md).
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# React Hooks Reference
|
|
2
|
+
|
|
3
|
+
Advanced custom hooks and patterns.
|
|
4
|
+
|
|
5
|
+
## References
|
|
6
|
+
|
|
7
|
+
- [**Custom Hooks Library**](custom-hooks.md) - Common custom hook implementations.
|
|
8
|
+
- [**Advanced Patterns**](advanced-patterns.md) - Complex hook compositions.
|
|
9
|
+
|
|
10
|
+
## Custom Hooks Library
|
|
11
|
+
|
|
12
|
+
```jsx
|
|
13
|
+
// useLocalStorage - Persist state in localStorage
|
|
14
|
+
function useLocalStorage(key, initialValue) {
|
|
15
|
+
const [storedValue, setStoredValue] = useState(() => {
|
|
16
|
+
try {
|
|
17
|
+
const item = window.localStorage.getItem(key);
|
|
18
|
+
return item ? JSON.parse(item) : initialValue;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error(error);
|
|
21
|
+
return initialValue;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const setValue = (value) => {
|
|
26
|
+
try {
|
|
27
|
+
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
28
|
+
setStoredValue(valueToStore);
|
|
29
|
+
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error(error);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return [storedValue, setValue];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// useDebounce - Debounce a value
|
|
39
|
+
function useDebounce(value, delay) {
|
|
40
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
44
|
+
return () => clearTimeout(handler);
|
|
45
|
+
}, [value, delay]);
|
|
46
|
+
|
|
47
|
+
return debouncedValue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// useWindowSize - Track window dimensions
|
|
51
|
+
function useWindowSize() {
|
|
52
|
+
const [size, setSize] = useState({
|
|
53
|
+
width: window.innerWidth,
|
|
54
|
+
height: window.innerHeight,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
const handleResize = () => {
|
|
59
|
+
setSize({
|
|
60
|
+
width: window.innerWidth,
|
|
61
|
+
height: window.innerHeight,
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
window.addEventListener('resize', handleResize);
|
|
66
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
return size;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// useOnClickOutside - Detect clicks outside an element
|
|
73
|
+
function useOnClickOutside(ref, handler) {
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
const listener = (event) => {
|
|
76
|
+
if (!ref.current || ref.current.contains(event.target)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
handler(event);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
document.addEventListener('mousedown', listener);
|
|
83
|
+
document.addEventListener('touchstart', listener);
|
|
84
|
+
|
|
85
|
+
return () => {
|
|
86
|
+
document.removeEventListener('mousedown', listener);
|
|
87
|
+
document.removeEventListener('touchstart', listener);
|
|
88
|
+
};
|
|
89
|
+
}, [ref, handler]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// useIntersectionObserver - Detect element visibility
|
|
93
|
+
function useIntersectionObserver(ref, options) {
|
|
94
|
+
const [isIntersecting, setIsIntersecting] = useState(false);
|
|
95
|
+
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
const observer = new IntersectionObserver(([entry]) => {
|
|
98
|
+
setIsIntersecting(entry.isIntersecting);
|
|
99
|
+
}, options);
|
|
100
|
+
|
|
101
|
+
if (ref.current) {
|
|
102
|
+
observer.observe(ref.current);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return () => observer.disconnect();
|
|
106
|
+
}, [ref, options]);
|
|
107
|
+
|
|
108
|
+
return isIntersecting;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// usePrevious - Get previous value
|
|
112
|
+
function usePrevious(value) {
|
|
113
|
+
const ref = useRef();
|
|
114
|
+
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
ref.current = value;
|
|
117
|
+
}, [value]);
|
|
118
|
+
|
|
119
|
+
return ref.current;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// useToggle - Boolean toggle
|
|
123
|
+
function useToggle(initialValue = false) {
|
|
124
|
+
const [value, setValue] = useState(initialValue);
|
|
125
|
+
|
|
126
|
+
const toggle = useCallback(() => {
|
|
127
|
+
setValue(v => !v);
|
|
128
|
+
}, []);
|
|
129
|
+
|
|
130
|
+
return [value, toggle];
|
|
131
|
+
}
|
|
132
|
+
```
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: react-hooks
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
triggers: [hooks, useEffect, useState, custom hooks]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# React Hooks
|
|
8
|
+
|
|
9
|
+
Modern React with hooks and functional components.
|
|
10
|
+
|
|
11
|
+
## useState
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
const [count, setCount] = useState(0);
|
|
15
|
+
const [user, setUser] = useState<User | null>(null);
|
|
16
|
+
|
|
17
|
+
// Functional updates for derived state
|
|
18
|
+
setCount(prev => prev + 1);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## useEffect
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
// Run on mount only
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
fetchData();
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
// Run when dependency changes
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
fetchUser(userId);
|
|
32
|
+
}, [userId]);
|
|
33
|
+
|
|
34
|
+
// Cleanup
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const sub = subscribe();
|
|
37
|
+
return () => sub.unsubscribe();
|
|
38
|
+
}, []);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Custom Hooks
|
|
42
|
+
|
|
43
|
+
Extract reusable logic:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
function useDebounce<T>(value: T, delay: number): T {
|
|
47
|
+
const [debounced, setDebounced] = useState(value);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const timer = setTimeout(() => setDebounced(value), delay);
|
|
51
|
+
return () => clearTimeout(timer);
|
|
52
|
+
}, [value, delay]);
|
|
53
|
+
|
|
54
|
+
return debounced;
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## useMemo / useCallback
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
// Memoize expensive computation
|
|
62
|
+
const sorted = useMemo(() => items.sort(compare), [items]);
|
|
63
|
+
|
|
64
|
+
// Stable callback reference
|
|
65
|
+
const handleClick = useCallback(() => {
|
|
66
|
+
doSomething(id);
|
|
67
|
+
}, [id]);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## useRef
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
74
|
+
|
|
75
|
+
// Focus on mount
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
inputRef.current?.focus();
|
|
78
|
+
}, []);
|
|
79
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: React Performance
|
|
3
|
+
description: Optimization strategies for React applications (Client & Server).
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [react, performance, optimization, nextjs]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.tsx', '**/*.jsx']
|
|
8
|
+
keywords: [waterfall, bundle, lazy, suspense, dynamic]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# React Performance
|
|
12
|
+
|
|
13
|
+
## **Priority: P0 (CRITICAL)**
|
|
14
|
+
|
|
15
|
+
Strategies to minimize waterfalls, bundle size, and render cost.
|
|
16
|
+
|
|
17
|
+
## Elimination of Waterfalls (P0)
|
|
18
|
+
|
|
19
|
+
- **Parallel Data**: Use `Promise.all` for independent fetches. Avoid sequential `await`.
|
|
20
|
+
- **Preload**: Start fetches before render (in event handlers or route loaders).
|
|
21
|
+
- **Suspense**: Use Suspense boundaries to stream partial content.
|
|
22
|
+
|
|
23
|
+
## Bundle Optimization (P0)
|
|
24
|
+
|
|
25
|
+
- **No Barrel Files**: Import directly `import { Btn } from './Btn'` vs `import { Btn } from './components'`.
|
|
26
|
+
- **Lazy Load**: `React.lazy` / `next/dynamic` for heavy components (Charts, Modals).
|
|
27
|
+
- **Defer**: Load 3rd-party scripts (Analytics) after hydration.
|
|
28
|
+
|
|
29
|
+
## Rendering & Re-renders (P1)
|
|
30
|
+
|
|
31
|
+
- **Isolation**: Move state down. Isolate heavy UI updates.
|
|
32
|
+
- **Context Splitting**: Split Context into `StateContext` (Data) and `DispatchContext` (Actions) to prevent consumers from re-rendering just because they need a setter.
|
|
33
|
+
- **Stability**: Use `useMemo` for passing objects/arrays to children to preserve referential equality checks (`React.memo`).
|
|
34
|
+
- **Virtualization**: `react-window` for lists > 50 items.
|
|
35
|
+
- **Content Visibility**: `content-visibility: auto` for off-screen CSS content.
|
|
36
|
+
- **Static Hoisting**: Extract static objects/JSX outside component scope.
|
|
37
|
+
- **Transitions**: `startTransition` for non-urgent UI updates.
|
|
38
|
+
|
|
39
|
+
## Parallelization (P1)
|
|
40
|
+
|
|
41
|
+
- **Web Workers**: Move heavy computation (Encryption, Image processing, Large Data Sorting) off the main thread using `Comlink` or `Worker`.
|
|
42
|
+
|
|
43
|
+
## Server Performance (RSC) (P1)
|
|
44
|
+
|
|
45
|
+
- **Caching**: `React.cache` for per-request deduplication.
|
|
46
|
+
- **Serialization**: Minimize props passing to Client Components (only IDs/primitives).
|
|
47
|
+
|
|
48
|
+
## Anti-Patterns
|
|
49
|
+
|
|
50
|
+
- **No `export *`**: Breaks tree-shaking.
|
|
51
|
+
- **No Sequential Await**: Causes waterfalls.
|
|
52
|
+
- **No Inline Objects**: `style={{}}` breaks strict equality checks (if memoized).
|
|
53
|
+
- **No Heavy Libs**: Avoid moment/lodash (use dayjs/radash).
|
|
54
|
+
|
|
55
|
+
## Code
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
// Parallel Fetching (Good)
|
|
59
|
+
const [user, posts] = await Promise.all([getUser(), getPosts()]);
|
|
60
|
+
|
|
61
|
+
// Bundle Optimized Import (Good)
|
|
62
|
+
import { Button } from './components/Button'; // Not from './components'
|
|
63
|
+
|
|
64
|
+
// Static Hoist (Good)
|
|
65
|
+
const STATIC_CONFIG = { theme: 'dark' };
|
|
66
|
+
function Component() {
|
|
67
|
+
return <div config={STATIC_CONFIG} />;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# React Performance Reference
|
|
2
|
+
|
|
3
|
+
Advanced optimization techniques and profiling.
|
|
4
|
+
|
|
5
|
+
## References
|
|
6
|
+
|
|
7
|
+
- [**Profiling**](profiling.md) - React DevTools Profiler usage.
|
|
8
|
+
- [**Bundle Analysis**](bundle-analysis.md) - Analyzing and reducing bundle size.
|
|
9
|
+
|
|
10
|
+
## React DevTools Profiler
|
|
11
|
+
|
|
12
|
+
```jsx
|
|
13
|
+
// Wrap components to profile
|
|
14
|
+
import { Profiler } from 'react';
|
|
15
|
+
|
|
16
|
+
function onRenderCallback(
|
|
17
|
+
id, // component id
|
|
18
|
+
phase, // "mount" or "update"
|
|
19
|
+
actualDuration, // time spent rendering
|
|
20
|
+
baseDuration, // estimated time without memoization
|
|
21
|
+
startTime,
|
|
22
|
+
commitTime,
|
|
23
|
+
interactions
|
|
24
|
+
) {
|
|
25
|
+
console.log(`${id} (${phase}) took ${actualDuration}ms`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function App() {
|
|
29
|
+
return (
|
|
30
|
+
<Profiler id="App" onRender={onRenderCallback}>
|
|
31
|
+
<Dashboard />
|
|
32
|
+
</Profiler>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Bundle Analysis
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Analyze bundle size
|
|
41
|
+
npm install --save-dev webpack-bundle-analyzer
|
|
42
|
+
|
|
43
|
+
# Add to webpack config or use with Vite
|
|
44
|
+
npm run build -- --analyze
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Image Optimization
|
|
48
|
+
|
|
49
|
+
```jsx
|
|
50
|
+
// Lazy loading images
|
|
51
|
+
function OptimizedImage({ src, alt }) {
|
|
52
|
+
return (
|
|
53
|
+
<img
|
|
54
|
+
src={src}
|
|
55
|
+
alt={alt}
|
|
56
|
+
loading="lazy"
|
|
57
|
+
decoding="async"
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Next.js Image component (automatic optimization)
|
|
63
|
+
import Image from 'next/image';
|
|
64
|
+
|
|
65
|
+
function Hero() {
|
|
66
|
+
return (
|
|
67
|
+
<Image
|
|
68
|
+
src="/hero.jpg"
|
|
69
|
+
alt="Hero"
|
|
70
|
+
width={1200}
|
|
71
|
+
height={600}
|
|
72
|
+
priority
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Web Workers for Heavy Computation
|
|
79
|
+
|
|
80
|
+
```jsx
|
|
81
|
+
// worker.js
|
|
82
|
+
self.addEventListener('message', (e) => {
|
|
83
|
+
const result = heavyComputation(e.data);
|
|
84
|
+
self.postMessage(result);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Component
|
|
88
|
+
import { useEffect, useState } from 'react';
|
|
89
|
+
|
|
90
|
+
function HeavyComponent({ data }) {
|
|
91
|
+
const [result, setResult] = useState(null);
|
|
92
|
+
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
const worker = new Worker(new URL('./worker.js', import.meta.url));
|
|
95
|
+
|
|
96
|
+
worker.postMessage(data);
|
|
97
|
+
worker.onmessage = (e) => {
|
|
98
|
+
setResult(e.data);
|
|
99
|
+
worker.terminate();
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
return () => worker.terminate();
|
|
103
|
+
}, [data]);
|
|
104
|
+
|
|
105
|
+
return <div>{result}</div>;
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Debouncing and Throttling
|
|
110
|
+
|
|
111
|
+
```jsx
|
|
112
|
+
import { useDeferredValue, useState } from 'react';
|
|
113
|
+
|
|
114
|
+
// Built-in deferred value
|
|
115
|
+
function SearchResults() {
|
|
116
|
+
const [query, setQuery] = useState('');
|
|
117
|
+
const deferredQuery = useDeferredValue(query);
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<>
|
|
121
|
+
<input value={query} onChange={e => setQuery(e.target.value)} />
|
|
122
|
+
<Results query={deferredQuery} />
|
|
123
|
+
</>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Manual debounce
|
|
128
|
+
import { useEffect, useState } from 'react';
|
|
129
|
+
|
|
130
|
+
function useDebounce(value, delay) {
|
|
131
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
const handler = setTimeout(() => {
|
|
135
|
+
setDebouncedValue(value);
|
|
136
|
+
}, delay);
|
|
137
|
+
|
|
138
|
+
return () => clearTimeout(handler);
|
|
139
|
+
}, [value, delay]);
|
|
140
|
+
|
|
141
|
+
return debouncedValue;
|
|
142
|
+
}
|
|
143
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: React Security
|
|
3
|
+
description: Security practices for React (XSS, Auth, Dependencies).
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [react, security, xss, auth]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.tsx', '**/*.jsx']
|
|
8
|
+
keywords: [dangerouslySetInnerHTML, token, auth, xss]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# React Security
|
|
12
|
+
|
|
13
|
+
## **Priority: P0 (CRITICAL)**
|
|
14
|
+
|
|
15
|
+
Preventing vulnerabilities in client-side apps.
|
|
16
|
+
|
|
17
|
+
## Implementation Guidelines
|
|
18
|
+
|
|
19
|
+
- **XSS**: Avoid `dangerouslySetInnerHTML`. Sanitize via `DOMPurify` if needed.
|
|
20
|
+
- **URLs**: Validate `javascript:` protocols in user links.
|
|
21
|
+
- **Auth**: Store tokens in `HttpOnly` cookies. Avoid `localStorage`.
|
|
22
|
+
- **Deps**: Run `npm audit`. Pin versions.
|
|
23
|
+
- **Secrets**: Server-side only. No `.env` secrets in build.
|
|
24
|
+
- **CSP**: Strict Content-Security-Policy headers.
|
|
25
|
+
|
|
26
|
+
## Anti-Patterns
|
|
27
|
+
|
|
28
|
+
- **No `eval()`**: RCE risk.
|
|
29
|
+
- **No Serialized State**: Don't inject JSON into DOM without escaping.
|
|
30
|
+
- **No Client Logic for Permissions**: Backend must validate.
|
|
31
|
+
|
|
32
|
+
## Code
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import DOMPurify from 'dompurify';
|
|
36
|
+
|
|
37
|
+
// Safe HTML Injection
|
|
38
|
+
function SafeHtml({ content }) {
|
|
39
|
+
const clean = DOMPurify.sanitize(content);
|
|
40
|
+
return <div dangerouslySetInnerHTML={{ __html: clean }} />;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Bad Link Prevention
|
|
44
|
+
const safeUrl = url.startsWith('javascript:') ? '#' : url;
|
|
45
|
+
<a href={safeUrl}>Link</a>;
|
|
46
|
+
```
|