@qin_sunrise/tab
Version:
A lightweight tab management package based on zustand state management for React applications
259 lines (201 loc) • 6.29 kB
Markdown
# Migration Guide
This guide helps you migrate from the original tab functionality to the new `@qin_sunrise/tab` package.
## Before Migration (Original Implementation)
```tsx
// Using Redux Toolkit
import { useAppDispatch, useAppSelector } from '@/store';
import {
addTab,
removeTabById,
setActiveTabId,
selectTabs,
selectActiveTabId
} from '@/features/tab/tabStore';
function MyComponent() {
const dispatch = useAppDispatch();
const tabs = useAppSelector(selectTabs);
const activeTabId = useAppSelector(selectActiveTabId);
const handleAddTab = (route) => {
dispatch(addTab(route));
};
const handleRemoveTab = (tabId) => {
dispatch(removeTabById(tabId));
};
}
```
## After Migration (New @qin_sunrise/tab Package)
```tsx
// Using Zustand
import { useTabManager, useTabs, useActiveTabId } from '@qin_sunrise/tab';
function MyComponent() {
const { addTab, removeTabById } = useTabManager();
const tabs = useTabs();
const activeTabId = useActiveTabId();
const handleAddTab = (route) => {
addTab(route);
};
const handleRemoveTab = (tabId) => {
removeTabById(tabId);
};
}
```
## Major Changes
### 1. State Management
- **Before**: Using Redux Toolkit's `useAppDispatch` and `useAppSelector`
- **After**: Using Zustand's direct hooks
### 2. Store Creation
- **Before**: Redux store with slices
- **After**: Zustand store with `createTabStore()`
### 3. Hooks
- **Before**: Using custom hooks with Redux selectors
- **After**: Direct hooks from `@qin_sunrise/tab`
### 4. Actions
- **Before**: `dispatch(action())`
- **After**: Direct function calls
## Migration Steps
### Step 1: Install New Package
```bash
pnpm add @qin_sunrise/tab
```
### Step 2: Replace Imports
```tsx
// Remove old imports
// import { useAppDispatch, useAppSelector } from '@/store';
// import { addTab, removeTabById, selectTabs } from '@/features/tab/tabStore';
// Add new imports
import { useTabManager, useTabs, useActiveTabId } from '@qin_sunrise/tab';
```
### Step 3: Update Component Logic
```tsx
// Before
function MyComponent() {
const dispatch = useAppDispatch();
const tabs = useAppSelector(selectTabs);
const activeTabId = useAppSelector(selectActiveTabId);
const handleAddTab = (route) => {
dispatch(addTab(route));
};
}
// After
function MyComponent() {
const { addTab } = useTabManager();
const tabs = useTabs();
const activeTabId = useActiveTabId();
const handleAddTab = (route) => {
addTab(route);
};
}
```
### Step 4: Update All Related Components
#### Tab Management Component
```tsx
// Before
import { useAppDispatch, useAppSelector } from '@/store';
import {
addTab,
removeTabById,
setActiveTabId,
selectTabs,
selectActiveTabId
} from '@/features/tab/tabStore';
function TabBar() {
const dispatch = useAppDispatch();
const tabs = useAppSelector(selectTabs);
const activeTabId = useAppSelector(selectActiveTabId);
const handleTabClick = (tab) => {
dispatch(setActiveTabId(tab.id));
};
const handleCloseTab = (tabId) => {
dispatch(removeTabById(tabId));
};
}
// After
import { useTabManager, useTabs, useActiveTabId } from '@qin_sunrise/tab';
function TabBar() {
const { setActiveTabId, removeTabById } = useTabManager();
const tabs = useTabs();
const activeTabId = useActiveTabId();
const handleTabClick = (tab) => {
setActiveTabId(tab.id);
};
const handleCloseTab = (tabId) => {
removeTabById(tabId);
};
}
```
#### Route Integration Component
```tsx
// Before
import { useAppDispatch } from '@/store';
import { addTab } from '@/features/tab/tabStore';
function RouteHandler() {
const dispatch = useAppDispatch();
useEffect(() => {
dispatch(addTab({
id: route.path,
label: route.title,
path: route.path
}));
}, [route]);
}
// After
import { useTabManager } from '@qin_sunrise/tab';
function RouteHandler() {
const { addTab } = useTabManager();
useEffect(() => {
addTab({
id: route.path,
label: route.title,
path: route.path
});
}, [route]);
}
```
## Feature Comparison
| Feature | Before (Redux) | After (Zustand) |
|---------|----------------|------------------|
| Add Tab | `dispatch(addTab(tab))` | `addTab(tab)` |
| Remove Tab | `dispatch(removeTabById(id))` | `removeTabById(id)` |
| Activate Tab | `dispatch(setActiveTabId(id))` | `setActiveTabId(id)` |
| Get Tab List | `useAppSelector(selectTabs)` | `useTabs()` |
| Get Active Tab | `useAppSelector(selectActiveTabId)` | `useActiveTabId()` |
| Clear Operations | `dispatch(clearAllTabs())` | `clearAllTabs()` |
## Configuration Options
The new package supports configuration options:
```tsx
import { createTabStore } from '@qin_sunrise/tab';
const tabStore = createTabStore({
cache: true, // Enable persistence
storageKey: 'my-tabs', // Custom storage key
homePath: '/dashboard' // Custom home path
});
```
## Important Notes
1. **Type Safety**: The new package provides complete TypeScript support
2. **Performance**: Zustand is lighter than Redux and performs better
3. **Persistence**: Built-in localStorage support with configurable options
4. **Compatibility**: Maintains all original functionality with cleaner API
## Troubleshooting
### Common Issues
1. **Import Errors**: Make sure `@qin_sunrise/tab` package is correctly installed
2. **Type Errors**: Check if TypeScript types are correctly imported
3. **State Not Updating**: Ensure correct hooks are being used
### Debugging Tips
```tsx
// Debug state changes
import { useTabStore } from '@qin_sunrise/tab';
function DebugComponent() {
const store = useTabStore();
useEffect(() => {
console.log('Tab store:', store.getState());
}, [store]);
}
```
## Summary
Migration to `@qin_sunrise/tab` package provides:
- ? Cleaner API
- ? Better performance
- ? Complete TypeScript support
- ? Built-in persistence
- ? Better development experience
The migration process is relatively simple, mainly replacing imports and removing dispatch calls.