devskill 2.0.2
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/README.md +123 -0
- package/README.vn.md +104 -0
- package/SKILL_GUIDE.vn.md +252 -0
- package/bin/devskill.js +11 -0
- package/meta.ts +123 -0
- package/package.json +21 -0
- package/publish.sh +50 -0
- package/scripts/cli.ts +556 -0
- package/skills/builderx_api-contexts/SKILL.md +63 -0
- package/skills/builderx_api-contexts/references/core-multi-outbox.md +57 -0
- package/skills/builderx_api-controllers/SKILL.md +49 -0
- package/skills/builderx_api-controllers/references/core-fallback.md +62 -0
- package/skills/builderx_api-schemas/SKILL.md +76 -0
- package/skills/builderx_api-schemas/references/core-schema.md +78 -0
- package/skills/builderx_spa-api/SKILL.md +67 -0
- package/skills/builderx_spa-api/references/base-api.md +97 -0
- package/skills/builderx_spa-api/references/fetch.md +70 -0
- package/skills/builderx_spa-design/SKILL.md +82 -0
- package/skills/builderx_spa-design/references/core-text-design.md +64 -0
- package/skills/builderx_spa-design/references/features-feedback-actions.md +76 -0
- package/skills/builderx_spa-design/references/features-forms.md +91 -0
- package/skills/builderx_spa-design/references/features-layout-navigation.md +121 -0
- package/skills/builderx_spa-permission/SKILL.md +38 -0
- package/skills/builderx_spa-permission/references/has-permission.md +34 -0
- package/skills/composition-patterns/AGENTS.md +946 -0
- package/skills/composition-patterns/README.md +60 -0
- package/skills/composition-patterns/SKILL.md +89 -0
- package/skills/composition-patterns/SYNC.md +5 -0
- package/skills/composition-patterns/metadata.json +11 -0
- package/skills/composition-patterns/rules/_sections.md +29 -0
- package/skills/composition-patterns/rules/_template.md +24 -0
- package/skills/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/skills/composition-patterns/rules/architecture-compound-components.md +112 -0
- package/skills/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/skills/composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/skills/composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/skills/composition-patterns/rules/state-context-interface.md +191 -0
- package/skills/composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/skills/composition-patterns/rules/state-lift-state.md +125 -0
- package/skills/deploy-to-vercel/Archive.zip +0 -0
- package/skills/deploy-to-vercel/SKILL.md +296 -0
- package/skills/deploy-to-vercel/SYNC.md +5 -0
- package/skills/deploy-to-vercel/resources/deploy-codex.sh +301 -0
- package/skills/deploy-to-vercel/resources/deploy.sh +301 -0
- package/skills/pinia/SKILL.md +105 -0
- package/skills/pinia/references/api-in-composables.md +139 -0
- package/skills/pinia/references/setup-stores.md +105 -0
- package/skills/pinia/references/using-in-components.md +91 -0
- package/skills/pinia-options/SKILL.md +72 -0
- package/skills/pinia-options/references/core-option-stores.md +149 -0
- package/skills/pinia-options/references/using-in-options-api.md +105 -0
- package/skills/react-best-practices/AGENTS.md +3373 -0
- package/skills/react-best-practices/README.md +123 -0
- package/skills/react-best-practices/SKILL.md +143 -0
- package/skills/react-best-practices/SYNC.md +5 -0
- package/skills/react-best-practices/metadata.json +15 -0
- package/skills/react-best-practices/rules/_sections.md +46 -0
- package/skills/react-best-practices/rules/_template.md +28 -0
- package/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/skills/react-best-practices/rules/async-dependencies.md +51 -0
- package/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills/react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/skills/react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/react-best-practices/rules/server-hoist-static-io.md +142 -0
- package/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/skills/react-native-skills/AGENTS.md +2897 -0
- package/skills/react-native-skills/README.md +165 -0
- package/skills/react-native-skills/SKILL.md +121 -0
- package/skills/react-native-skills/SYNC.md +5 -0
- package/skills/react-native-skills/metadata.json +16 -0
- package/skills/react-native-skills/rules/_sections.md +86 -0
- package/skills/react-native-skills/rules/_template.md +28 -0
- package/skills/react-native-skills/rules/animation-derived-value.md +53 -0
- package/skills/react-native-skills/rules/animation-gesture-detector-press.md +95 -0
- package/skills/react-native-skills/rules/animation-gpu-properties.md +65 -0
- package/skills/react-native-skills/rules/design-system-compound-components.md +66 -0
- package/skills/react-native-skills/rules/fonts-config-plugin.md +71 -0
- package/skills/react-native-skills/rules/imports-design-system-folder.md +68 -0
- package/skills/react-native-skills/rules/js-hoist-intl.md +61 -0
- package/skills/react-native-skills/rules/list-performance-callbacks.md +44 -0
- package/skills/react-native-skills/rules/list-performance-function-references.md +132 -0
- package/skills/react-native-skills/rules/list-performance-images.md +53 -0
- package/skills/react-native-skills/rules/list-performance-inline-objects.md +97 -0
- package/skills/react-native-skills/rules/list-performance-item-expensive.md +94 -0
- package/skills/react-native-skills/rules/list-performance-item-memo.md +82 -0
- package/skills/react-native-skills/rules/list-performance-item-types.md +104 -0
- package/skills/react-native-skills/rules/list-performance-virtualize.md +67 -0
- package/skills/react-native-skills/rules/monorepo-native-deps-in-app.md +46 -0
- package/skills/react-native-skills/rules/monorepo-single-dependency-versions.md +63 -0
- package/skills/react-native-skills/rules/navigation-native-navigators.md +188 -0
- package/skills/react-native-skills/rules/react-compiler-destructure-functions.md +50 -0
- package/skills/react-native-skills/rules/react-compiler-reanimated-shared-values.md +48 -0
- package/skills/react-native-skills/rules/react-state-dispatcher.md +91 -0
- package/skills/react-native-skills/rules/react-state-fallback.md +56 -0
- package/skills/react-native-skills/rules/react-state-minimize.md +65 -0
- package/skills/react-native-skills/rules/rendering-no-falsy-and.md +74 -0
- package/skills/react-native-skills/rules/rendering-text-in-text-component.md +36 -0
- package/skills/react-native-skills/rules/scroll-position-no-state.md +82 -0
- package/skills/react-native-skills/rules/state-ground-truth.md +80 -0
- package/skills/react-native-skills/rules/ui-expo-image.md +66 -0
- package/skills/react-native-skills/rules/ui-image-gallery.md +104 -0
- package/skills/react-native-skills/rules/ui-measure-views.md +78 -0
- package/skills/react-native-skills/rules/ui-menus.md +174 -0
- package/skills/react-native-skills/rules/ui-native-modals.md +77 -0
- package/skills/react-native-skills/rules/ui-pressable.md +61 -0
- package/skills/react-native-skills/rules/ui-safe-area-scroll.md +65 -0
- package/skills/react-native-skills/rules/ui-scrollview-content-inset.md +45 -0
- package/skills/react-native-skills/rules/ui-styling.md +87 -0
- package/skills/slidev/LICENSE.md +21 -0
- package/skills/slidev/README.md +61 -0
- package/skills/slidev/SKILL.md +189 -0
- package/skills/slidev/SYNC.md +5 -0
- package/skills/slidev/references/animation-click-marker.md +37 -0
- package/skills/slidev/references/animation-drawing.md +68 -0
- package/skills/slidev/references/animation-rough-marker.md +53 -0
- package/skills/slidev/references/api-slide-hooks.md +37 -0
- package/skills/slidev/references/build-og-image.md +36 -0
- package/skills/slidev/references/build-pdf.md +40 -0
- package/skills/slidev/references/build-remote-assets.md +34 -0
- package/skills/slidev/references/build-seo-meta.md +43 -0
- package/skills/slidev/references/code-groups.md +64 -0
- package/skills/slidev/references/code-import-snippet.md +55 -0
- package/skills/slidev/references/code-line-highlighting.md +50 -0
- package/skills/slidev/references/code-line-numbers.md +46 -0
- package/skills/slidev/references/code-magic-move.md +57 -0
- package/skills/slidev/references/code-max-height.md +37 -0
- package/skills/slidev/references/code-twoslash.md +42 -0
- package/skills/slidev/references/core-animations.md +196 -0
- package/skills/slidev/references/core-cli.md +140 -0
- package/skills/slidev/references/core-components.md +197 -0
- package/skills/slidev/references/core-exporting.md +148 -0
- package/skills/slidev/references/core-frontmatter.md +195 -0
- package/skills/slidev/references/core-global-context.md +155 -0
- package/skills/slidev/references/core-headmatter.md +188 -0
- package/skills/slidev/references/core-hosting.md +152 -0
- package/skills/slidev/references/core-layouts.md +286 -0
- package/skills/slidev/references/core-syntax.md +155 -0
- package/skills/slidev/references/diagram-latex.md +55 -0
- package/skills/slidev/references/diagram-mermaid.md +44 -0
- package/skills/slidev/references/diagram-plantuml.md +45 -0
- package/skills/slidev/references/editor-monaco-run.md +44 -0
- package/skills/slidev/references/editor-monaco-write.md +24 -0
- package/skills/slidev/references/editor-monaco.md +50 -0
- package/skills/slidev/references/editor-prettier.md +40 -0
- package/skills/slidev/references/editor-side.md +23 -0
- package/skills/slidev/references/editor-vscode.md +55 -0
- package/skills/slidev/references/layout-canvas-size.md +25 -0
- package/skills/slidev/references/layout-draggable.md +57 -0
- package/skills/slidev/references/layout-global-layers.md +50 -0
- package/skills/slidev/references/layout-slots.md +75 -0
- package/skills/slidev/references/layout-transform.md +33 -0
- package/skills/slidev/references/layout-zoom.md +39 -0
- package/skills/slidev/references/presenter-notes-ruby.md +35 -0
- package/skills/slidev/references/presenter-recording.md +30 -0
- package/skills/slidev/references/presenter-remote.md +40 -0
- package/skills/slidev/references/presenter-timer.md +34 -0
- package/skills/slidev/references/style-direction.md +34 -0
- package/skills/slidev/references/style-icons.md +46 -0
- package/skills/slidev/references/style-scoped.md +50 -0
- package/skills/slidev/references/syntax-block-frontmatter.md +39 -0
- package/skills/slidev/references/syntax-frontmatter-merging.md +49 -0
- package/skills/slidev/references/syntax-importing-slides.md +60 -0
- package/skills/slidev/references/syntax-mdc.md +51 -0
- package/skills/slidev/references/tool-eject-theme.md +27 -0
- package/skills/tsdown/LICENSE.md +22 -0
- package/skills/tsdown/README.md +77 -0
- package/skills/tsdown/SKILL.md +407 -0
- package/skills/tsdown/SYNC.md +5 -0
- package/skills/tsdown/references/README.md +139 -0
- package/skills/tsdown/references/advanced-benchmark.md +8 -0
- package/skills/tsdown/references/advanced-ci.md +89 -0
- package/skills/tsdown/references/advanced-hooks.md +363 -0
- package/skills/tsdown/references/advanced-plugins.md +381 -0
- package/skills/tsdown/references/advanced-programmatic.md +378 -0
- package/skills/tsdown/references/advanced-rolldown-options.md +117 -0
- package/skills/tsdown/references/guide-getting-started.md +178 -0
- package/skills/tsdown/references/guide-introduction.md +42 -0
- package/skills/tsdown/references/guide-migrate-from-tsup.md +189 -0
- package/skills/tsdown/references/option-cjs-default.md +98 -0
- package/skills/tsdown/references/option-cleaning.md +275 -0
- package/skills/tsdown/references/option-config-file.md +281 -0
- package/skills/tsdown/references/option-css.md +301 -0
- package/skills/tsdown/references/option-dependencies.md +385 -0
- package/skills/tsdown/references/option-dts.md +251 -0
- package/skills/tsdown/references/option-entry.md +211 -0
- package/skills/tsdown/references/option-exe.md +120 -0
- package/skills/tsdown/references/option-lint.md +127 -0
- package/skills/tsdown/references/option-log-level.md +91 -0
- package/skills/tsdown/references/option-minification.md +177 -0
- package/skills/tsdown/references/option-output-directory.md +270 -0
- package/skills/tsdown/references/option-output-format.md +181 -0
- package/skills/tsdown/references/option-package-exports.md +320 -0
- package/skills/tsdown/references/option-platform.md +256 -0
- package/skills/tsdown/references/option-root.md +88 -0
- package/skills/tsdown/references/option-shims.md +299 -0
- package/skills/tsdown/references/option-sourcemap.md +301 -0
- package/skills/tsdown/references/option-target.md +222 -0
- package/skills/tsdown/references/option-tree-shaking.md +335 -0
- package/skills/tsdown/references/option-unbundle.md +310 -0
- package/skills/tsdown/references/option-watch-mode.md +261 -0
- package/skills/tsdown/references/recipe-react.md +338 -0
- package/skills/tsdown/references/recipe-solid.md +46 -0
- package/skills/tsdown/references/recipe-svelte.md +54 -0
- package/skills/tsdown/references/recipe-vue.md +387 -0
- package/skills/tsdown/references/recipe-wasm.md +125 -0
- package/skills/tsdown/references/reference-cli.md +472 -0
- package/skills/turborepo/LICENSE.md +7 -0
- package/skills/turborepo/SKILL.md +951 -0
- package/skills/turborepo/SYNC.md +5 -0
- package/skills/turborepo/command/turborepo.md +70 -0
- package/skills/turborepo/references/best-practices/RULE.md +241 -0
- package/skills/turborepo/references/best-practices/dependencies.md +246 -0
- package/skills/turborepo/references/best-practices/packages.md +335 -0
- package/skills/turborepo/references/best-practices/structure.md +297 -0
- package/skills/turborepo/references/boundaries/RULE.md +126 -0
- package/skills/turborepo/references/caching/RULE.md +153 -0
- package/skills/turborepo/references/caching/gotchas.md +190 -0
- package/skills/turborepo/references/caching/remote-cache.md +127 -0
- package/skills/turborepo/references/ci/RULE.md +79 -0
- package/skills/turborepo/references/ci/github-actions.md +162 -0
- package/skills/turborepo/references/ci/patterns.md +145 -0
- package/skills/turborepo/references/ci/vercel.md +103 -0
- package/skills/turborepo/references/cli/RULE.md +100 -0
- package/skills/turborepo/references/cli/commands.md +297 -0
- package/skills/turborepo/references/configuration/RULE.md +235 -0
- package/skills/turborepo/references/configuration/global-options.md +239 -0
- package/skills/turborepo/references/configuration/gotchas.md +368 -0
- package/skills/turborepo/references/configuration/tasks.md +325 -0
- package/skills/turborepo/references/environment/RULE.md +123 -0
- package/skills/turborepo/references/environment/gotchas.md +175 -0
- package/skills/turborepo/references/environment/modes.md +101 -0
- package/skills/turborepo/references/filtering/RULE.md +148 -0
- package/skills/turborepo/references/filtering/patterns.md +152 -0
- package/skills/turborepo/references/watch/RULE.md +99 -0
- package/skills/vercel-cli-with-tokens/SKILL.md +328 -0
- package/skills/vercel-cli-with-tokens/SYNC.md +5 -0
- package/skills/vue/SKILL.md +90 -0
- package/skills/vue/references/composables.md +54 -0
- package/skills/vue/references/lifecycle.md +31 -0
- package/skills/vue/references/props-emits.md +62 -0
- package/skills/vue/references/provide-inject.md +47 -0
- package/skills/vue/references/state.md +65 -0
- package/skills/vue-antdv-tailwind/SKILL.md +33 -0
- package/skills/vue-antdv-tailwind/references/styling-rules.md +61 -0
- package/skills/vue-best-practices/LICENSE.md +21 -0
- package/skills/vue-best-practices/SKILL.md +154 -0
- package/skills/vue-best-practices/SYNC.md +5 -0
- package/skills/vue-best-practices/references/animation-class-based-technique.md +254 -0
- package/skills/vue-best-practices/references/animation-state-driven-technique.md +291 -0
- package/skills/vue-best-practices/references/component-async.md +97 -0
- package/skills/vue-best-practices/references/component-data-flow.md +307 -0
- package/skills/vue-best-practices/references/component-fallthrough-attrs.md +174 -0
- package/skills/vue-best-practices/references/component-keep-alive.md +137 -0
- package/skills/vue-best-practices/references/component-slots.md +216 -0
- package/skills/vue-best-practices/references/component-suspense.md +228 -0
- package/skills/vue-best-practices/references/component-teleport.md +108 -0
- package/skills/vue-best-practices/references/component-transition-group.md +128 -0
- package/skills/vue-best-practices/references/component-transition.md +125 -0
- package/skills/vue-best-practices/references/composables.md +290 -0
- package/skills/vue-best-practices/references/directives.md +162 -0
- package/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -0
- package/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -0
- package/skills/vue-best-practices/references/perf-virtualize-large-lists.md +187 -0
- package/skills/vue-best-practices/references/plugins.md +166 -0
- package/skills/vue-best-practices/references/reactivity.md +344 -0
- package/skills/vue-best-practices/references/render-functions.md +201 -0
- package/skills/vue-best-practices/references/sfc.md +310 -0
- package/skills/vue-best-practices/references/state-management.md +135 -0
- package/skills/vue-best-practices/references/updated-hook-performance.md +187 -0
- package/skills/vue-jsx-best-practices/LICENSE.md +21 -0
- package/skills/vue-jsx-best-practices/SKILL.md +12 -0
- package/skills/vue-jsx-best-practices/SYNC.md +5 -0
- package/skills/vue-jsx-best-practices/reference/render-function-jsx-vue-vs-react.md +141 -0
- package/skills/vue-options/SKILL.md +98 -0
- package/skills/vue-options/references/lifecycle.md +107 -0
- package/skills/vue-options/references/mixins.md +96 -0
- package/skills/vue-options/references/props-emits.md +106 -0
- package/skills/vue-options/references/provide-inject.md +92 -0
- package/skills/vue-options/references/state.md +115 -0
- package/skills/vue-options-api-best-practices/LICENSE.md +21 -0
- package/skills/vue-options-api-best-practices/SKILL.md +23 -0
- package/skills/vue-options-api-best-practices/SYNC.md +5 -0
- package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-lifecycle-hooks.md +95 -0
- package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-methods.md +68 -0
- package/skills/vue-options-api-best-practices/reference/stateful-methods-lifecycle.md +61 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-arrow-functions-validators.md +141 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-computed-return-types.md +192 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-proptype-complex-types.md +212 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-provide-inject-limitations.md +135 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-type-event-handlers.md +202 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-use-definecomponent.md +172 -0
- package/skills/vue-options-api-best-practices/reference/ts-strict-mode-options-api.md +197 -0
- package/skills/vue-pinia-best-practices/LICENSE.md +21 -0
- package/skills/vue-pinia-best-practices/SKILL.md +21 -0
- package/skills/vue-pinia-best-practices/SYNC.md +5 -0
- package/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md +248 -0
- package/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md +227 -0
- package/skills/vue-pinia-best-practices/reference/pinia-store-destructuring-breaks-reactivity.md +193 -0
- package/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md +238 -0
- package/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md +262 -0
- package/skills/vue-pinia-best-practices/reference/store-method-binding-parentheses.md +191 -0
- package/skills/vue-router-best-practices/LICENSE.md +21 -0
- package/skills/vue-router-best-practices/SKILL.md +23 -0
- package/skills/vue-router-best-practices/SYNC.md +5 -0
- package/skills/vue-router-best-practices/reference/router-beforeenter-no-param-trigger.md +167 -0
- package/skills/vue-router-best-practices/reference/router-beforerouteenter-no-this.md +176 -0
- package/skills/vue-router-best-practices/reference/router-guard-async-await-pattern.md +227 -0
- package/skills/vue-router-best-practices/reference/router-navigation-guard-infinite-loop.md +187 -0
- package/skills/vue-router-best-practices/reference/router-navigation-guard-next-deprecated.md +150 -0
- package/skills/vue-router-best-practices/reference/router-param-change-no-lifecycle.md +181 -0
- package/skills/vue-router-best-practices/reference/router-simple-routing-cleanup.md +209 -0
- package/skills/vue-router-best-practices/reference/router-use-vue-router-for-production.md +183 -0
- package/skills/vue-testing-best-practices/LICENSE.md +21 -0
- package/skills/vue-testing-best-practices/SKILL.md +29 -0
- package/skills/vue-testing-best-practices/SYNC.md +5 -0
- package/skills/vue-testing-best-practices/reference/async-component-testing.md +163 -0
- package/skills/vue-testing-best-practices/reference/teleport-testing-complexity.md +158 -0
- package/skills/vue-testing-best-practices/reference/testing-async-await-flushpromises.md +175 -0
- package/skills/vue-testing-best-practices/reference/testing-browser-vs-node-runners.md +208 -0
- package/skills/vue-testing-best-practices/reference/testing-component-blackbox-approach.md +144 -0
- package/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md +238 -0
- package/skills/vue-testing-best-practices/reference/testing-e2e-playwright-recommended.md +242 -0
- package/skills/vue-testing-best-practices/reference/testing-no-snapshot-only.md +197 -0
- package/skills/vue-testing-best-practices/reference/testing-pinia-store-setup.md +228 -0
- package/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md +229 -0
- package/skills/vue-testing-best-practices/reference/testing-vitest-recommended-for-vue.md +204 -0
- package/skills/vueuse-functions/LICENSE.md +21 -0
- package/skills/vueuse-functions/SKILL.md +419 -0
- package/skills/vueuse-functions/SYNC.md +5 -0
- package/skills/vueuse-functions/references/computedAsync.md +195 -0
- package/skills/vueuse-functions/references/computedEager.md +62 -0
- package/skills/vueuse-functions/references/computedInject.md +137 -0
- package/skills/vueuse-functions/references/computedWithControl.md +98 -0
- package/skills/vueuse-functions/references/createEventHook.md +86 -0
- package/skills/vueuse-functions/references/createGenericProjection.md +25 -0
- package/skills/vueuse-functions/references/createGlobalState.md +95 -0
- package/skills/vueuse-functions/references/createInjectionState.md +215 -0
- package/skills/vueuse-functions/references/createProjection.md +31 -0
- package/skills/vueuse-functions/references/createRef.md +54 -0
- package/skills/vueuse-functions/references/createReusableTemplate.md +357 -0
- package/skills/vueuse-functions/references/createSharedComposable.md +42 -0
- package/skills/vueuse-functions/references/createTemplatePromise.md +306 -0
- package/skills/vueuse-functions/references/createUnrefFn.md +51 -0
- package/skills/vueuse-functions/references/extendRef.md +76 -0
- package/skills/vueuse-functions/references/from.md +80 -0
- package/skills/vueuse-functions/references/get.md +30 -0
- package/skills/vueuse-functions/references/injectLocal.md +35 -0
- package/skills/vueuse-functions/references/isDefined.md +31 -0
- package/skills/vueuse-functions/references/logicAnd.md +40 -0
- package/skills/vueuse-functions/references/logicNot.md +36 -0
- package/skills/vueuse-functions/references/logicOr.md +40 -0
- package/skills/vueuse-functions/references/makeDestructurable.md +41 -0
- package/skills/vueuse-functions/references/onClickOutside.md +221 -0
- package/skills/vueuse-functions/references/onElementRemoval.md +88 -0
- package/skills/vueuse-functions/references/onKeyStroke.md +211 -0
- package/skills/vueuse-functions/references/onLongPress.md +227 -0
- package/skills/vueuse-functions/references/onStartTyping.md +53 -0
- package/skills/vueuse-functions/references/provideLocal.md +37 -0
- package/skills/vueuse-functions/references/reactify.md +144 -0
- package/skills/vueuse-functions/references/reactifyObject.md +62 -0
- package/skills/vueuse-functions/references/reactiveComputed.md +34 -0
- package/skills/vueuse-functions/references/reactiveOmit.md +86 -0
- package/skills/vueuse-functions/references/reactivePick.md +106 -0
- package/skills/vueuse-functions/references/refAutoReset.md +46 -0
- package/skills/vueuse-functions/references/refDebounced.md +81 -0
- package/skills/vueuse-functions/references/refDefault.md +36 -0
- package/skills/vueuse-functions/references/refManualReset.md +44 -0
- package/skills/vueuse-functions/references/refThrottled.md +99 -0
- package/skills/vueuse-functions/references/refWithControl.md +146 -0
- package/skills/vueuse-functions/references/set.md +30 -0
- package/skills/vueuse-functions/references/syncRef.md +195 -0
- package/skills/vueuse-functions/references/syncRefs.md +128 -0
- package/skills/vueuse-functions/references/templateRef.md +86 -0
- package/skills/vueuse-functions/references/toObserver.md +38 -0
- package/skills/vueuse-functions/references/toReactive.md +41 -0
- package/skills/vueuse-functions/references/toRef.md +75 -0
- package/skills/vueuse-functions/references/toRefs.md +81 -0
- package/skills/vueuse-functions/references/tryOnBeforeMount.md +34 -0
- package/skills/vueuse-functions/references/tryOnBeforeUnmount.md +32 -0
- package/skills/vueuse-functions/references/tryOnMounted.md +34 -0
- package/skills/vueuse-functions/references/tryOnScopeDispose.md +31 -0
- package/skills/vueuse-functions/references/tryOnUnmounted.md +32 -0
- package/skills/vueuse-functions/references/unrefElement.md +54 -0
- package/skills/vueuse-functions/references/until.md +161 -0
- package/skills/vueuse-functions/references/useAbs.md +31 -0
- package/skills/vueuse-functions/references/useActiveElement.md +85 -0
- package/skills/vueuse-functions/references/useAnimate.md +181 -0
- package/skills/vueuse-functions/references/useArrayDifference.md +84 -0
- package/skills/vueuse-functions/references/useArrayEvery.md +59 -0
- package/skills/vueuse-functions/references/useArrayFilter.md +63 -0
- package/skills/vueuse-functions/references/useArrayFind.md +50 -0
- package/skills/vueuse-functions/references/useArrayFindIndex.md +59 -0
- package/skills/vueuse-functions/references/useArrayFindLast.md +52 -0
- package/skills/vueuse-functions/references/useArrayIncludes.md +63 -0
- package/skills/vueuse-functions/references/useArrayJoin.md +74 -0
- package/skills/vueuse-functions/references/useArrayMap.md +59 -0
- package/skills/vueuse-functions/references/useArrayReduce.md +81 -0
- package/skills/vueuse-functions/references/useArraySome.md +59 -0
- package/skills/vueuse-functions/references/useArrayUnique.md +76 -0
- package/skills/vueuse-functions/references/useAsyncQueue.md +136 -0
- package/skills/vueuse-functions/references/useAsyncState.md +185 -0
- package/skills/vueuse-functions/references/useAsyncValidator.md +70 -0
- package/skills/vueuse-functions/references/useAuth.md +123 -0
- package/skills/vueuse-functions/references/useAverage.md +36 -0
- package/skills/vueuse-functions/references/useAxios.md +325 -0
- package/skills/vueuse-functions/references/useBase64.md +136 -0
- package/skills/vueuse-functions/references/useBattery.md +78 -0
- package/skills/vueuse-functions/references/useBluetooth.md +175 -0
- package/skills/vueuse-functions/references/useBreakpoints.md +172 -0
- package/skills/vueuse-functions/references/useBroadcastChannel.md +74 -0
- package/skills/vueuse-functions/references/useBrowserLocation.md +83 -0
- package/skills/vueuse-functions/references/useCached.md +52 -0
- package/skills/vueuse-functions/references/useCeil.md +31 -0
- package/skills/vueuse-functions/references/useChangeCase.md +79 -0
- package/skills/vueuse-functions/references/useClamp.md +85 -0
- package/skills/vueuse-functions/references/useClipboard.md +123 -0
- package/skills/vueuse-functions/references/useClipboardItems.md +94 -0
- package/skills/vueuse-functions/references/useCloned.md +91 -0
- package/skills/vueuse-functions/references/useColorMode.md +172 -0
- package/skills/vueuse-functions/references/useConfirmDialog.md +159 -0
- package/skills/vueuse-functions/references/useCookies.md +162 -0
- package/skills/vueuse-functions/references/useCountdown.md +105 -0
- package/skills/vueuse-functions/references/useCounter.md +86 -0
- package/skills/vueuse-functions/references/useCssSupports.md +35 -0
- package/skills/vueuse-functions/references/useCssVar.md +50 -0
- package/skills/vueuse-functions/references/useCurrentElement.md +61 -0
- package/skills/vueuse-functions/references/useCycleList.md +75 -0
- package/skills/vueuse-functions/references/useDark.md +144 -0
- package/skills/vueuse-functions/references/useDateFormat.md +145 -0
- package/skills/vueuse-functions/references/useDebounceFn.md +100 -0
- package/skills/vueuse-functions/references/useDebouncedRefHistory.md +40 -0
- package/skills/vueuse-functions/references/useDeviceMotion.md +86 -0
- package/skills/vueuse-functions/references/useDeviceOrientation.md +62 -0
- package/skills/vueuse-functions/references/useDevicePixelRatio.md +44 -0
- package/skills/vueuse-functions/references/useDevicesList.md +90 -0
- package/skills/vueuse-functions/references/useDisplayMedia.md +71 -0
- package/skills/vueuse-functions/references/useDocumentVisibility.md +45 -0
- package/skills/vueuse-functions/references/useDraggable.md +317 -0
- package/skills/vueuse-functions/references/useDrauu.md +65 -0
- package/skills/vueuse-functions/references/useDropZone.md +83 -0
- package/skills/vueuse-functions/references/useElementBounding.md +131 -0
- package/skills/vueuse-functions/references/useElementByPoint.md +48 -0
- package/skills/vueuse-functions/references/useElementHover.md +79 -0
- package/skills/vueuse-functions/references/useElementSize.md +78 -0
- package/skills/vueuse-functions/references/useElementVisibility.md +123 -0
- package/skills/vueuse-functions/references/useEventBus.md +101 -0
- package/skills/vueuse-functions/references/useEventListener.md +226 -0
- package/skills/vueuse-functions/references/useEventSource.md +204 -0
- package/skills/vueuse-functions/references/useExtractedObservable.md +198 -0
- package/skills/vueuse-functions/references/useEyeDropper.md +71 -0
- package/skills/vueuse-functions/references/useFavicon.md +67 -0
- package/skills/vueuse-functions/references/useFetch.md +546 -0
- package/skills/vueuse-functions/references/useFileDialog.md +91 -0
- package/skills/vueuse-functions/references/useFileSystemAccess.md +162 -0
- package/skills/vueuse-functions/references/useFirestore.md +129 -0
- package/skills/vueuse-functions/references/useFloor.md +31 -0
- package/skills/vueuse-functions/references/useFocus.md +99 -0
- package/skills/vueuse-functions/references/useFocusTrap.md +245 -0
- package/skills/vueuse-functions/references/useFocusWithin.md +57 -0
- package/skills/vueuse-functions/references/useFps.md +28 -0
- package/skills/vueuse-functions/references/useFullscreen.md +75 -0
- package/skills/vueuse-functions/references/useFuse.md +107 -0
- package/skills/vueuse-functions/references/useGamepad.md +222 -0
- package/skills/vueuse-functions/references/useGeolocation.md +85 -0
- package/skills/vueuse-functions/references/useIDBKeyval.md +93 -0
- package/skills/vueuse-functions/references/useIdle.md +88 -0
- package/skills/vueuse-functions/references/useImage.md +86 -0
- package/skills/vueuse-functions/references/useInfiniteScroll.md +157 -0
- package/skills/vueuse-functions/references/useIntersectionObserver.md +118 -0
- package/skills/vueuse-functions/references/useInterval.md +112 -0
- package/skills/vueuse-functions/references/useIntervalFn.md +50 -0
- package/skills/vueuse-functions/references/useIpcRenderer.md +144 -0
- package/skills/vueuse-functions/references/useIpcRendererInvoke.md +58 -0
- package/skills/vueuse-functions/references/useIpcRendererOn.md +52 -0
- package/skills/vueuse-functions/references/useJwt.md +57 -0
- package/skills/vueuse-functions/references/useKeyModifier.md +87 -0
- package/skills/vueuse-functions/references/useLastChanged.md +63 -0
- package/skills/vueuse-functions/references/useLocalStorage.md +41 -0
- package/skills/vueuse-functions/references/useMagicKeys.md +245 -0
- package/skills/vueuse-functions/references/useManualRefHistory.md +204 -0
- package/skills/vueuse-functions/references/useMath.md +47 -0
- package/skills/vueuse-functions/references/useMax.md +36 -0
- package/skills/vueuse-functions/references/useMediaControls.md +571 -0
- package/skills/vueuse-functions/references/useMediaQuery.md +53 -0
- package/skills/vueuse-functions/references/useMemoize.md +175 -0
- package/skills/vueuse-functions/references/useMemory.md +71 -0
- package/skills/vueuse-functions/references/useMin.md +36 -0
- package/skills/vueuse-functions/references/useMounted.md +38 -0
- package/skills/vueuse-functions/references/useMouse.md +113 -0
- package/skills/vueuse-functions/references/useMouseInElement.md +123 -0
- package/skills/vueuse-functions/references/useMousePressed.md +112 -0
- package/skills/vueuse-functions/references/useMutationObserver.md +61 -0
- package/skills/vueuse-functions/references/useNProgress.md +78 -0
- package/skills/vueuse-functions/references/useNavigatorLanguage.md +57 -0
- package/skills/vueuse-functions/references/useNetwork.md +106 -0
- package/skills/vueuse-functions/references/useNow.md +79 -0
- package/skills/vueuse-functions/references/useObjectUrl.md +55 -0
- package/skills/vueuse-functions/references/useObservable.md +91 -0
- package/skills/vueuse-functions/references/useOffsetPagination.md +199 -0
- package/skills/vueuse-functions/references/useOnline.md +41 -0
- package/skills/vueuse-functions/references/usePageLeave.md +42 -0
- package/skills/vueuse-functions/references/useParallax.md +58 -0
- package/skills/vueuse-functions/references/useParentElement.md +54 -0
- package/skills/vueuse-functions/references/usePerformanceObserver.md +48 -0
- package/skills/vueuse-functions/references/usePermission.md +79 -0
- package/skills/vueuse-functions/references/usePointer.md +89 -0
- package/skills/vueuse-functions/references/usePointerLock.md +60 -0
- package/skills/vueuse-functions/references/usePointerSwipe.md +80 -0
- package/skills/vueuse-functions/references/usePrecision.md +49 -0
- package/skills/vueuse-functions/references/usePreferredColorScheme.md +42 -0
- package/skills/vueuse-functions/references/usePreferredContrast.md +42 -0
- package/skills/vueuse-functions/references/usePreferredDark.md +41 -0
- package/skills/vueuse-functions/references/usePreferredLanguages.md +41 -0
- package/skills/vueuse-functions/references/usePreferredReducedMotion.md +42 -0
- package/skills/vueuse-functions/references/usePreferredReducedTransparency.md +42 -0
- package/skills/vueuse-functions/references/usePrevious.md +40 -0
- package/skills/vueuse-functions/references/useProjection.md +38 -0
- package/skills/vueuse-functions/references/useQRCode.md +53 -0
- package/skills/vueuse-functions/references/useRTDB.md +83 -0
- package/skills/vueuse-functions/references/useRafFn.md +68 -0
- package/skills/vueuse-functions/references/useRefHistory.md +285 -0
- package/skills/vueuse-functions/references/useResizeObserver.md +109 -0
- package/skills/vueuse-functions/references/useRound.md +31 -0
- package/skills/vueuse-functions/references/useRouteHash.md +27 -0
- package/skills/vueuse-functions/references/useRouteParams.md +38 -0
- package/skills/vueuse-functions/references/useRouteQuery.md +79 -0
- package/skills/vueuse-functions/references/useSSRWidth.md +47 -0
- package/skills/vueuse-functions/references/useScreenOrientation.md +96 -0
- package/skills/vueuse-functions/references/useScreenSafeArea.md +60 -0
- package/skills/vueuse-functions/references/useScriptTag.md +116 -0
- package/skills/vueuse-functions/references/useScroll.md +238 -0
- package/skills/vueuse-functions/references/useScrollLock.md +66 -0
- package/skills/vueuse-functions/references/useSessionStorage.md +41 -0
- package/skills/vueuse-functions/references/useShare.md +68 -0
- package/skills/vueuse-functions/references/useSortable.md +235 -0
- package/skills/vueuse-functions/references/useSorted.md +90 -0
- package/skills/vueuse-functions/references/useSpeechRecognition.md +94 -0
- package/skills/vueuse-functions/references/useSpeechSynthesis.md +105 -0
- package/skills/vueuse-functions/references/useStepper.md +137 -0
- package/skills/vueuse-functions/references/useStorage.md +278 -0
- package/skills/vueuse-functions/references/useStorageAsync.md +136 -0
- package/skills/vueuse-functions/references/useStyleTag.md +131 -0
- package/skills/vueuse-functions/references/useSubject.md +77 -0
- package/skills/vueuse-functions/references/useSubscription.md +33 -0
- package/skills/vueuse-functions/references/useSum.md +36 -0
- package/skills/vueuse-functions/references/useSupported.md +29 -0
- package/skills/vueuse-functions/references/useSwipe.md +75 -0
- package/skills/vueuse-functions/references/useTemplateRefsList.md +37 -0
- package/skills/vueuse-functions/references/useTextDirection.md +75 -0
- package/skills/vueuse-functions/references/useTextSelection.md +40 -0
- package/skills/vueuse-functions/references/useTextareaAutosize.md +97 -0
- package/skills/vueuse-functions/references/useThrottleFn.md +57 -0
- package/skills/vueuse-functions/references/useThrottledRefHistory.md +47 -0
- package/skills/vueuse-functions/references/useTimeAgo.md +154 -0
- package/skills/vueuse-functions/references/useTimeAgoIntl.md +117 -0
- package/skills/vueuse-functions/references/useTimeout.md +113 -0
- package/skills/vueuse-functions/references/useTimeoutFn.md +51 -0
- package/skills/vueuse-functions/references/useTimeoutPoll.md +47 -0
- package/skills/vueuse-functions/references/useTimestamp.md +89 -0
- package/skills/vueuse-functions/references/useTitle.md +113 -0
- package/skills/vueuse-functions/references/useToNumber.md +54 -0
- package/skills/vueuse-functions/references/useToString.md +34 -0
- package/skills/vueuse-functions/references/useToggle.md +103 -0
- package/skills/vueuse-functions/references/useTransition.md +265 -0
- package/skills/vueuse-functions/references/useTrunc.md +33 -0
- package/skills/vueuse-functions/references/useUrlSearchParams.md +121 -0
- package/skills/vueuse-functions/references/useUserMedia.md +1138 -0
- package/skills/vueuse-functions/references/useVModel.md +182 -0
- package/skills/vueuse-functions/references/useVModels.md +67 -0
- package/skills/vueuse-functions/references/useVibrate.md +87 -0
- package/skills/vueuse-functions/references/useVirtualList.md +182 -0
- package/skills/vueuse-functions/references/useWakeLock.md +50 -0
- package/skills/vueuse-functions/references/useWebNotification.md +176 -0
- package/skills/vueuse-functions/references/useWebSocket.md +299 -0
- package/skills/vueuse-functions/references/useWebWorker.md +60 -0
- package/skills/vueuse-functions/references/useWebWorkerFn.md +102 -0
- package/skills/vueuse-functions/references/useWindowFocus.md +46 -0
- package/skills/vueuse-functions/references/useWindowScroll.md +61 -0
- package/skills/vueuse-functions/references/useWindowSize.md +76 -0
- package/skills/vueuse-functions/references/useZoomFactor.md +53 -0
- package/skills/vueuse-functions/references/useZoomLevel.md +53 -0
- package/skills/vueuse-functions/references/watchArray.md +53 -0
- package/skills/vueuse-functions/references/watchAtMost.md +55 -0
- package/skills/vueuse-functions/references/watchDebounced.md +101 -0
- package/skills/vueuse-functions/references/watchDeep.md +54 -0
- package/skills/vueuse-functions/references/watchExtractedObservable.md +192 -0
- package/skills/vueuse-functions/references/watchIgnorable.md +120 -0
- package/skills/vueuse-functions/references/watchImmediate.md +44 -0
- package/skills/vueuse-functions/references/watchOnce.md +41 -0
- package/skills/vueuse-functions/references/watchPausable.md +86 -0
- package/skills/vueuse-functions/references/watchThrottled.md +108 -0
- package/skills/vueuse-functions/references/watchTriggerable.md +98 -0
- package/skills/vueuse-functions/references/watchWithFilter.md +54 -0
- package/skills/vueuse-functions/references/whenever.md +100 -0
- package/skills/web-design-guidelines/SKILL.md +39 -0
- package/skills/web-design-guidelines/SYNC.md +5 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Pass Primitives to List Items for Memoization
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables effective memo() comparison
|
|
5
|
+
tags: lists, performance, memo, primitives
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Pass Primitives to List Items for Memoization
|
|
9
|
+
|
|
10
|
+
When possible, pass only primitive values (strings, numbers, booleans) as props
|
|
11
|
+
to list item components. Primitives enable shallow comparison in `memo()` to
|
|
12
|
+
work correctly, skipping re-renders when values haven't changed.
|
|
13
|
+
|
|
14
|
+
**Incorrect (object prop requires deep comparison):**
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
type User = { id: string; name: string; email: string; avatar: string }
|
|
18
|
+
|
|
19
|
+
const UserRow = memo(function UserRow({ user }: { user: User }) {
|
|
20
|
+
// memo() compares user by reference, not value
|
|
21
|
+
// If parent creates new user object, this re-renders even if data is same
|
|
22
|
+
return <Text>{user.name}</Text>
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
renderItem={({ item }) => <UserRow user={item} />}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This can still be optimized, but it is harder to memoize properly.
|
|
29
|
+
|
|
30
|
+
**Correct (primitive props enable shallow comparison):**
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
const UserRow = memo(function UserRow({
|
|
34
|
+
id,
|
|
35
|
+
name,
|
|
36
|
+
email,
|
|
37
|
+
}: {
|
|
38
|
+
id: string
|
|
39
|
+
name: string
|
|
40
|
+
email: string
|
|
41
|
+
}) {
|
|
42
|
+
// memo() compares each primitive directly
|
|
43
|
+
// Re-renders only if id, name, or email actually changed
|
|
44
|
+
return <Text>{name}</Text>
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
renderItem={({ item }) => (
|
|
48
|
+
<UserRow id={item.id} name={item.name} email={item.email} />
|
|
49
|
+
)}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Pass only what you need:**
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
// Incorrect: passing entire item when you only need name
|
|
56
|
+
<UserRow user={item} />
|
|
57
|
+
|
|
58
|
+
// Correct: pass only the fields the component uses
|
|
59
|
+
<UserRow name={item.name} avatarUrl={item.avatar} />
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**For callbacks, hoist or use item ID:**
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
// Incorrect: inline function creates new reference
|
|
66
|
+
<UserRow name={item.name} onPress={() => handlePress(item.id)} />
|
|
67
|
+
|
|
68
|
+
// Correct: pass ID, handle in child
|
|
69
|
+
<UserRow id={item.id} name={item.name} />
|
|
70
|
+
|
|
71
|
+
const UserRow = memo(function UserRow({ id, name }: Props) {
|
|
72
|
+
const handlePress = useCallback(() => {
|
|
73
|
+
// use id here
|
|
74
|
+
}, [id])
|
|
75
|
+
return <Pressable onPress={handlePress}><Text>{name}</Text></Pressable>
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Primitive props make memoization predictable and effective.
|
|
80
|
+
|
|
81
|
+
**Note:** If you have the React Compiler enabled, you do not need to use
|
|
82
|
+
`memo()` or `useCallback()`, but the object references still apply.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Item Types for Heterogeneous Lists
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: efficient recycling, less layout thrashing
|
|
5
|
+
tags: list, performance, recycling, heterogeneous, LegendList
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Item Types for Heterogeneous Lists
|
|
9
|
+
|
|
10
|
+
When a list has different item layouts (messages, images, headers, etc.), use a
|
|
11
|
+
`type` field on each item and provide `getItemType` to the list. This puts items
|
|
12
|
+
into separate recycling pools so a message component never gets recycled into an
|
|
13
|
+
image component.
|
|
14
|
+
|
|
15
|
+
**Incorrect (single component with conditionals):**
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
type Item = { id: string; text?: string; imageUrl?: string; isHeader?: boolean }
|
|
19
|
+
|
|
20
|
+
function ListItem({ item }: { item: Item }) {
|
|
21
|
+
if (item.isHeader) {
|
|
22
|
+
return <HeaderItem title={item.text} />
|
|
23
|
+
}
|
|
24
|
+
if (item.imageUrl) {
|
|
25
|
+
return <ImageItem url={item.imageUrl} />
|
|
26
|
+
}
|
|
27
|
+
return <MessageItem text={item.text} />
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function Feed({ items }: { items: Item[] }) {
|
|
31
|
+
return (
|
|
32
|
+
<LegendList
|
|
33
|
+
data={items}
|
|
34
|
+
renderItem={({ item }) => <ListItem item={item} />}
|
|
35
|
+
recycleItems
|
|
36
|
+
/>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Correct (typed items with separate components):**
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
type HeaderItem = { id: string; type: 'header'; title: string }
|
|
45
|
+
type MessageItem = { id: string; type: 'message'; text: string }
|
|
46
|
+
type ImageItem = { id: string; type: 'image'; url: string }
|
|
47
|
+
type FeedItem = HeaderItem | MessageItem | ImageItem
|
|
48
|
+
|
|
49
|
+
function Feed({ items }: { items: FeedItem[] }) {
|
|
50
|
+
return (
|
|
51
|
+
<LegendList
|
|
52
|
+
data={items}
|
|
53
|
+
keyExtractor={(item) => item.id}
|
|
54
|
+
getItemType={(item) => item.type}
|
|
55
|
+
renderItem={({ item }) => {
|
|
56
|
+
switch (item.type) {
|
|
57
|
+
case 'header':
|
|
58
|
+
return <SectionHeader title={item.title} />
|
|
59
|
+
case 'message':
|
|
60
|
+
return <MessageRow text={item.text} />
|
|
61
|
+
case 'image':
|
|
62
|
+
return <ImageRow url={item.url} />
|
|
63
|
+
}
|
|
64
|
+
}}
|
|
65
|
+
recycleItems
|
|
66
|
+
/>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Why this matters:**
|
|
72
|
+
|
|
73
|
+
- **Recycling efficiency**: Items with the same type share a recycling pool
|
|
74
|
+
- **No layout thrashing**: A header never recycles into an image cell
|
|
75
|
+
- **Type safety**: TypeScript can narrow the item type in each branch
|
|
76
|
+
- **Better size estimation**: Use `getEstimatedItemSize` with `itemType` for
|
|
77
|
+
accurate estimates per type
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
<LegendList
|
|
81
|
+
data={items}
|
|
82
|
+
keyExtractor={(item) => item.id}
|
|
83
|
+
getItemType={(item) => item.type}
|
|
84
|
+
getEstimatedItemSize={(index, item, itemType) => {
|
|
85
|
+
switch (itemType) {
|
|
86
|
+
case 'header':
|
|
87
|
+
return 48
|
|
88
|
+
case 'message':
|
|
89
|
+
return 72
|
|
90
|
+
case 'image':
|
|
91
|
+
return 300
|
|
92
|
+
default:
|
|
93
|
+
return 72
|
|
94
|
+
}
|
|
95
|
+
}}
|
|
96
|
+
renderItem={({ item }) => {
|
|
97
|
+
/* ... */
|
|
98
|
+
}}
|
|
99
|
+
recycleItems
|
|
100
|
+
/>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Reference:
|
|
104
|
+
[LegendList getItemType](https://legendapp.com/open-source/list/api/props/#getitemtype-v2)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use a List Virtualizer for Any List
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: reduced memory, faster mounts
|
|
5
|
+
tags: lists, performance, virtualization, scrollview
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use a List Virtualizer for Any List
|
|
9
|
+
|
|
10
|
+
Use a list virtualizer like LegendList or FlashList instead of ScrollView with
|
|
11
|
+
mapped children—even for short lists. Virtualizers only render visible items,
|
|
12
|
+
reducing memory usage and mount time. ScrollView renders all children upfront,
|
|
13
|
+
which gets expensive quickly.
|
|
14
|
+
|
|
15
|
+
**Incorrect (ScrollView renders all items at once):**
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
function Feed({ items }: { items: Item[] }) {
|
|
19
|
+
return (
|
|
20
|
+
<ScrollView>
|
|
21
|
+
{items.map((item) => (
|
|
22
|
+
<ItemCard key={item.id} item={item} />
|
|
23
|
+
))}
|
|
24
|
+
</ScrollView>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
// 50 items = 50 components mounted, even if only 10 visible
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Correct (virtualizer renders only visible items):**
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { LegendList } from '@legendapp/list'
|
|
34
|
+
|
|
35
|
+
function Feed({ items }: { items: Item[] }) {
|
|
36
|
+
return (
|
|
37
|
+
<LegendList
|
|
38
|
+
data={items}
|
|
39
|
+
// if you aren't using React Compiler, wrap these with useCallback
|
|
40
|
+
renderItem={({ item }) => <ItemCard item={item} />}
|
|
41
|
+
keyExtractor={(item) => item.id}
|
|
42
|
+
estimatedItemSize={80}
|
|
43
|
+
/>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
// Only ~10-15 visible items mounted at a time
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Alternative (FlashList):**
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { FlashList } from '@shopify/flash-list'
|
|
53
|
+
|
|
54
|
+
function Feed({ items }: { items: Item[] }) {
|
|
55
|
+
return (
|
|
56
|
+
<FlashList
|
|
57
|
+
data={items}
|
|
58
|
+
// if you aren't using React Compiler, wrap these with useCallback
|
|
59
|
+
renderItem={({ item }) => <ItemCard item={item} />}
|
|
60
|
+
keyExtractor={(item) => item.id}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Benefits apply to any screen with scrollable content—profiles, settings, feeds,
|
|
67
|
+
search results. Default to virtualization.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Install Native Dependencies in App Directory
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: required for autolinking to work
|
|
5
|
+
tags: monorepo, native, autolinking, installation
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Install Native Dependencies in App Directory
|
|
9
|
+
|
|
10
|
+
In a monorepo, packages with native code must be installed in the native app's
|
|
11
|
+
directory directly. Autolinking only scans the app's `node_modules`—it won't
|
|
12
|
+
find native dependencies installed in other packages.
|
|
13
|
+
|
|
14
|
+
**Incorrect (native dep in shared package only):**
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
packages/
|
|
18
|
+
ui/
|
|
19
|
+
package.json # has react-native-reanimated
|
|
20
|
+
app/
|
|
21
|
+
package.json # missing react-native-reanimated
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Autolinking fails—native code not linked.
|
|
25
|
+
|
|
26
|
+
**Correct (native dep in app directory):**
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
packages/
|
|
30
|
+
ui/
|
|
31
|
+
package.json # has react-native-reanimated
|
|
32
|
+
app/
|
|
33
|
+
package.json # also has react-native-reanimated
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
// packages/app/package.json
|
|
38
|
+
{
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"react-native-reanimated": "3.16.1"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Even if the shared package uses the native dependency, the app must also list it
|
|
46
|
+
for autolinking to detect and link the native code.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Single Dependency Versions Across Monorepo
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: avoids duplicate bundles, version conflicts
|
|
5
|
+
tags: monorepo, dependencies, installation
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Single Dependency Versions Across Monorepo
|
|
9
|
+
|
|
10
|
+
Use a single version of each dependency across all packages in your monorepo.
|
|
11
|
+
Prefer exact versions over ranges. Multiple versions cause duplicate code in
|
|
12
|
+
bundles, runtime conflicts, and inconsistent behavior across packages.
|
|
13
|
+
|
|
14
|
+
Use a tool like syncpack to enforce this. As a last resort, use yarn resolutions
|
|
15
|
+
or npm overrides.
|
|
16
|
+
|
|
17
|
+
**Incorrect (version ranges, multiple versions):**
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
// packages/app/package.json
|
|
21
|
+
{
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"react-native-reanimated": "^3.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// packages/ui/package.json
|
|
28
|
+
{
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"react-native-reanimated": "^3.5.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Correct (exact versions, single source of truth):**
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
// package.json (root)
|
|
39
|
+
{
|
|
40
|
+
"pnpm": {
|
|
41
|
+
"overrides": {
|
|
42
|
+
"react-native-reanimated": "3.16.1"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// packages/app/package.json
|
|
48
|
+
{
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"react-native-reanimated": "3.16.1"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// packages/ui/package.json
|
|
55
|
+
{
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"react-native-reanimated": "3.16.1"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Use your package manager's override/resolution feature to enforce versions at
|
|
63
|
+
the root. When adding dependencies, specify exact versions without `^` or `~`.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Native Navigators for Navigation
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: native performance, platform-appropriate UI
|
|
5
|
+
tags: navigation, react-navigation, expo-router, native-stack, tabs
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Native Navigators for Navigation
|
|
9
|
+
|
|
10
|
+
Always use native navigators instead of JS-based ones. Native navigators use
|
|
11
|
+
platform APIs (UINavigationController on iOS, Fragment on Android) for better
|
|
12
|
+
performance and native behavior.
|
|
13
|
+
|
|
14
|
+
**For stacks:** Use `@react-navigation/native-stack` or expo-router's default
|
|
15
|
+
stack (which uses native-stack). Avoid `@react-navigation/stack`.
|
|
16
|
+
|
|
17
|
+
**For tabs:** Use `react-native-bottom-tabs` (native) or expo-router's native
|
|
18
|
+
tabs. Avoid `@react-navigation/bottom-tabs` when native feel matters.
|
|
19
|
+
|
|
20
|
+
### Stack Navigation
|
|
21
|
+
|
|
22
|
+
**Incorrect (JS stack navigator):**
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { createStackNavigator } from '@react-navigation/stack'
|
|
26
|
+
|
|
27
|
+
const Stack = createStackNavigator()
|
|
28
|
+
|
|
29
|
+
function App() {
|
|
30
|
+
return (
|
|
31
|
+
<Stack.Navigator>
|
|
32
|
+
<Stack.Screen name='Home' component={HomeScreen} />
|
|
33
|
+
<Stack.Screen name='Details' component={DetailsScreen} />
|
|
34
|
+
</Stack.Navigator>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Correct (native stack with react-navigation):**
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
|
43
|
+
|
|
44
|
+
const Stack = createNativeStackNavigator()
|
|
45
|
+
|
|
46
|
+
function App() {
|
|
47
|
+
return (
|
|
48
|
+
<Stack.Navigator>
|
|
49
|
+
<Stack.Screen name='Home' component={HomeScreen} />
|
|
50
|
+
<Stack.Screen name='Details' component={DetailsScreen} />
|
|
51
|
+
</Stack.Navigator>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Correct (expo-router uses native stack by default):**
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
// app/_layout.tsx
|
|
60
|
+
import { Stack } from 'expo-router'
|
|
61
|
+
|
|
62
|
+
export default function Layout() {
|
|
63
|
+
return <Stack />
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Tab Navigation
|
|
68
|
+
|
|
69
|
+
**Incorrect (JS bottom tabs):**
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
|
|
73
|
+
|
|
74
|
+
const Tab = createBottomTabNavigator()
|
|
75
|
+
|
|
76
|
+
function App() {
|
|
77
|
+
return (
|
|
78
|
+
<Tab.Navigator>
|
|
79
|
+
<Tab.Screen name='Home' component={HomeScreen} />
|
|
80
|
+
<Tab.Screen name='Settings' component={SettingsScreen} />
|
|
81
|
+
</Tab.Navigator>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Correct (native bottom tabs with react-navigation):**
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation'
|
|
90
|
+
|
|
91
|
+
const Tab = createNativeBottomTabNavigator()
|
|
92
|
+
|
|
93
|
+
function App() {
|
|
94
|
+
return (
|
|
95
|
+
<Tab.Navigator>
|
|
96
|
+
<Tab.Screen
|
|
97
|
+
name='Home'
|
|
98
|
+
component={HomeScreen}
|
|
99
|
+
options={{
|
|
100
|
+
tabBarIcon: () => ({ sfSymbol: 'house' }),
|
|
101
|
+
}}
|
|
102
|
+
/>
|
|
103
|
+
<Tab.Screen
|
|
104
|
+
name='Settings'
|
|
105
|
+
component={SettingsScreen}
|
|
106
|
+
options={{
|
|
107
|
+
tabBarIcon: () => ({ sfSymbol: 'gear' }),
|
|
108
|
+
}}
|
|
109
|
+
/>
|
|
110
|
+
</Tab.Navigator>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Correct (expo-router native tabs):**
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
// app/(tabs)/_layout.tsx
|
|
119
|
+
import { NativeTabs } from 'expo-router/unstable-native-tabs'
|
|
120
|
+
|
|
121
|
+
export default function TabLayout() {
|
|
122
|
+
return (
|
|
123
|
+
<NativeTabs>
|
|
124
|
+
<NativeTabs.Trigger name='index'>
|
|
125
|
+
<NativeTabs.Trigger.Label>Home</NativeTabs.Trigger.Label>
|
|
126
|
+
<NativeTabs.Trigger.Icon sf='house.fill' md='home' />
|
|
127
|
+
</NativeTabs.Trigger>
|
|
128
|
+
<NativeTabs.Trigger name='settings'>
|
|
129
|
+
<NativeTabs.Trigger.Label>Settings</NativeTabs.Trigger.Label>
|
|
130
|
+
<NativeTabs.Trigger.Icon sf='gear' md='settings' />
|
|
131
|
+
</NativeTabs.Trigger>
|
|
132
|
+
</NativeTabs>
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
On iOS, native tabs automatically enable `contentInsetAdjustmentBehavior` on the
|
|
138
|
+
first `ScrollView` at the root of each tab screen, so content scrolls correctly
|
|
139
|
+
behind the translucent tab bar. If you need to disable this, use
|
|
140
|
+
`disableAutomaticContentInsets` on the trigger.
|
|
141
|
+
|
|
142
|
+
### Prefer Native Header Options Over Custom Components
|
|
143
|
+
|
|
144
|
+
**Incorrect (custom header component):**
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
<Stack.Screen
|
|
148
|
+
name='Profile'
|
|
149
|
+
component={ProfileScreen}
|
|
150
|
+
options={{
|
|
151
|
+
header: () => <CustomHeader title='Profile' />,
|
|
152
|
+
}}
|
|
153
|
+
/>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Correct (native header options):**
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
<Stack.Screen
|
|
160
|
+
name='Profile'
|
|
161
|
+
component={ProfileScreen}
|
|
162
|
+
options={{
|
|
163
|
+
title: 'Profile',
|
|
164
|
+
headerLargeTitleEnabled: true,
|
|
165
|
+
headerSearchBarOptions: {
|
|
166
|
+
placeholder: 'Search',
|
|
167
|
+
},
|
|
168
|
+
}}
|
|
169
|
+
/>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Native headers support iOS large titles, search bars, blur effects, and proper
|
|
173
|
+
safe area handling automatically.
|
|
174
|
+
|
|
175
|
+
### Why Native Navigators
|
|
176
|
+
|
|
177
|
+
- **Performance**: Native transitions and gestures run on the UI thread
|
|
178
|
+
- **Platform behavior**: Automatic iOS large titles, Android material design
|
|
179
|
+
- **System integration**: Scroll-to-top on tab tap, PiP avoidance, proper safe
|
|
180
|
+
areas
|
|
181
|
+
- **Accessibility**: Platform accessibility features work automatically
|
|
182
|
+
|
|
183
|
+
Reference:
|
|
184
|
+
|
|
185
|
+
- [React Navigation Native Stack](https://reactnavigation.org/docs/native-stack-navigator)
|
|
186
|
+
- [React Native Bottom Tabs with React Navigation](https://oss.callstack.com/react-native-bottom-tabs/docs/guides/usage-with-react-navigation)
|
|
187
|
+
- [React Native Bottom Tabs with Expo Router](https://oss.callstack.com/react-native-bottom-tabs/docs/guides/usage-with-expo-router)
|
|
188
|
+
- [Expo Router Native Tabs](https://docs.expo.dev/router/advanced/native-tabs)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Destructure Functions Early in Render (React Compiler)
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: stable references, fewer re-renders
|
|
5
|
+
tags: rerender, hooks, performance, react-compiler
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Destructure Functions Early in Render
|
|
9
|
+
|
|
10
|
+
This rule is only applicable if you are using the React Compiler.
|
|
11
|
+
|
|
12
|
+
Destructure functions from hooks at the top of render scope. Never dot into
|
|
13
|
+
objects to call functions. Destructured functions are stable references; dotting
|
|
14
|
+
creates new references and breaks memoization.
|
|
15
|
+
|
|
16
|
+
**Incorrect (dotting into object):**
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { useRouter } from 'expo-router'
|
|
20
|
+
|
|
21
|
+
function SaveButton(props) {
|
|
22
|
+
const router = useRouter()
|
|
23
|
+
|
|
24
|
+
// bad: react-compiler will key the cache on "props" and "router", which are objects that change each render
|
|
25
|
+
const handlePress = () => {
|
|
26
|
+
props.onSave()
|
|
27
|
+
router.push('/success') // unstable reference
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return <Button onPress={handlePress}>Save</Button>
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Correct (destructure early):**
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { useRouter } from 'expo-router'
|
|
38
|
+
|
|
39
|
+
function SaveButton({ onSave }) {
|
|
40
|
+
const { push } = useRouter()
|
|
41
|
+
|
|
42
|
+
// good: react-compiler will key on push and onSave
|
|
43
|
+
const handlePress = () => {
|
|
44
|
+
onSave()
|
|
45
|
+
push('/success') // stable reference
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return <Button onPress={handlePress}>Save</Button>
|
|
49
|
+
}
|
|
50
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use .get() and .set() for Reanimated Shared Values (not .value)
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: required for React Compiler compatibility
|
|
5
|
+
tags: reanimated, react-compiler, shared-values
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use .get() and .set() for Shared Values with React Compiler
|
|
9
|
+
|
|
10
|
+
With React Compiler enabled, use `.get()` and `.set()` instead of reading or
|
|
11
|
+
writing `.value` directly on Reanimated shared values. The compiler can't track
|
|
12
|
+
property access—explicit methods ensure correct behavior.
|
|
13
|
+
|
|
14
|
+
**Incorrect (breaks with React Compiler):**
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { useSharedValue } from 'react-native-reanimated'
|
|
18
|
+
|
|
19
|
+
function Counter() {
|
|
20
|
+
const count = useSharedValue(0)
|
|
21
|
+
|
|
22
|
+
const increment = () => {
|
|
23
|
+
count.value = count.value + 1 // opts out of react compiler
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return <Button onPress={increment} title={`Count: ${count.value}`} />
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Correct (React Compiler compatible):**
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { useSharedValue } from 'react-native-reanimated'
|
|
34
|
+
|
|
35
|
+
function Counter() {
|
|
36
|
+
const count = useSharedValue(0)
|
|
37
|
+
|
|
38
|
+
const increment = () => {
|
|
39
|
+
count.set(count.get() + 1)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return <Button onPress={increment} title={`Count: ${count.get()}`} />
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
See the
|
|
47
|
+
[Reanimated docs](https://docs.swmansion.com/react-native-reanimated/docs/core/useSharedValue/#react-compiler-support)
|
|
48
|
+
for more.
|