React Auto Key Plugin
Build plugin that auto-generates keys for transition() calls
Overview
The Auto Key Plugin for @ssgoi/react is a build-time plugin that automatically generates unique key values for transition() function calls.
Why Keys Are Needed
SSGOI requires unique key values to track element animation states. Without keys:
- Cannot distinguish between elements using the same transition
- Animation states are not preserved after page navigation
- Unexpected behavior when elements mount/unmount
What the Plugin Does
At build time, it analyzes all transition() calls and injects unique keys based on filename:line:column.
// Your code
<div ref={transition(fade())}>Content</div>
// Transformed code after build
<div ref={transition({ ...fade(), key: "page.tsx:15:6" })}>Content</div>
Installation & Setup
The plugin is included in the @ssgoi/react package. No separate installation needed.
Next.js (Webpack)
// next.config.ts
import type { NextConfig } from "next";
import SsgoiAutoKey from "@ssgoi/react/unplugin/webpack";
const nextConfig: NextConfig = {
webpack: (config) => {
config.plugins.push(SsgoiAutoKey());
return config;
},
};
export default nextConfig;
Vite
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import SsgoiAutoKey from "@ssgoi/react/unplugin/vite";
export default defineConfig({
plugins: [react(), SsgoiAutoKey()],
});
Rollup
// rollup.config.js
import SsgoiAutoKey from "@ssgoi/react/unplugin/rollup";
export default {
plugins: [SsgoiAutoKey()],
};
esbuild
import SsgoiAutoKey from "@ssgoi/react/unplugin/esbuild";
await esbuild.build({
plugins: [SsgoiAutoKey()],
});
Usage
Basic Usage (With Plugin)
When the plugin is configured, you can omit the key.
import { transition } from '@ssgoi/react';
import { fade, scale } from '@ssgoi/react/transitions';
function MyComponent() {
return (
<>
{/* key can be omitted - auto-generated */}
<div ref={transition(fade())}>
Fade effect
</div>
<div ref={transition(scale())}>
Scale effect
</div>
</>
);
}
Explicit Key
You can still specify an explicit key when needed. The plugin skips calls that already have a key.
<div ref={transition({
key: "my-custom-key", // explicit key
...fade()
})}>
Content
</div>
Lists (.map)
For lists rendered with .map(), JSX key is enough. The plugin reads the JSX key and generates filename:line:column:${jsxKey}.
function ItemList({ items }) {
return (
<ul>
{items.map((item) => (
<li
key={item.id} // JSX key is sufficient!
ref={transition(fade())} // plugin handles it
>
{item.name}
</li>
))}
</ul>
);
}
Generated key example: ItemList.tsx:8:10:item-1, ItemList.tsx:8:10:item-2, ...
Without Plugin
If not using the plugin, you must manually specify unique keys.
// Without plugin - key is required!
<div ref={transition({
key: "unique-key-1",
...fade()
})}>
Content
</div>
// Lists also require explicit keys
{items.map((item) => (
<li
key={item.id}
ref={transition({
key: `item-${item.id}`, // transition key also needed
...fade()
})}
>
{item.name}
</li>
))}
How It Works
1. Code Analysis
The plugin scans .tsx and .jsx files for transition() function calls.
2. Location-Based Key Generation
Generates unique keys based on source code location (filename, line, column).
filename:line:column
e.g., MyComponent.tsx:25:8
3. JSX Key Combination (Lists)
For elements inside .map(), it finds the parent JSX element's key prop and combines it.
filename:line:column:${jsxKey}
e.g., ItemList.tsx:8:10:item-123
4. Code Transformation
Transforms the original code to inject the key.
// Before
transition(fade())
// After
transition({ ...fade(), key: "MyComponent.tsx:25:8" })
Plugin Options
interface SsgoiAutoKeyOptions {
/**
* File extensions to process
* @default ['.tsx', '.jsx']
*/
include?: string[];
/**
* File patterns to exclude
* @default [/node_modules/]
*/
exclude?: (string | RegExp)[];
}
Example
// next.config.ts
import SsgoiAutoKey from "@ssgoi/react/unplugin/webpack";
const nextConfig = {
webpack: (config) => {
config.plugins.push(SsgoiAutoKey({
include: ['.tsx'], // only .tsx files
exclude: [/node_modules/, /\.test\.tsx$/], // exclude test files
}));
return config;
},
};
Important Notes
This plugin is React-only. It cannot be used with Svelte, Vue, Angular, or other frameworks.
Conditional Rendering: When different elements render at the same location based on conditions, they may get the same key. Use explicit keys in such cases.
// ⚠️ Caution: conditional rendering at same location
{isLoading
? <div ref={transition(fade())}>Loading...</div> // key: file:10:6
: <div ref={transition(fade())}>Content</div> // key: file:11:6 (different line, OK)
}
// ✅ Same line? Use explicit keys
{isLoading
? <div ref={transition({ key: "loading", ...fade() })}>Loading...</div>
: <div ref={transition({ key: "content", ...fade() })}>Content</div>
}
Debugging
To check generated keys during development, inspect the built code in browser devtools or log the transition:
const myTransition = transition(fade());
console.log(myTransition); // check key value