一键导入
manage-component-state
Manage component state and data flow in React components following best practices
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Manage component state and data flow in React components following best practices
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Add a new Recharts visualization with theme-aware styling to the dashboard
Add a new metric card to the dashboard with proper styling and components
Add Lucide React icons to components following project conventions
Add responsive layouts following mobile-first design principles with Tailwind CSS
Add a new shadcn/ui component to the project following the New York style variant
Add or customize theme colors in the CSS custom properties system
| name | manage-component-state |
| description | Manage component state and data flow in React components following best practices |
When managing state and data in this Next.js 15 dashboard:
Choose the right state management approach:
Local state with useState:
"use client";
import { useState } from "react";
export default function Component() {
const [count, setCount] = useState(0);
const [user, setUser] = useState({ name: "", email: "" });
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
Derived state (avoid duplicate state):
// Good: Derive from props/state
const totalRevenue = stats.reduce((sum, stat) => sum + stat.value, 0);
// Avoid: Storing derived data in state
// const [totalRevenue, setTotalRevenue] = useState(0);
Complex state with useReducer:
import { useReducer } from "react";
const initialState = { count: 0, loading: false };
function reducer(state, action) {
switch (action.type) {
case "increment":
return { ...state, count: state.count + 1 };
case "setLoading":
return { ...state, loading: action.payload };
default:
return state;
}
}
export default function Component() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<button onClick={() => dispatch({ type: "increment" })}>
{state.count}
</button>
);
}
Shared state with Context:
// contexts/DashboardContext.tsx
"use client";
import { createContext, useContext, useState } from "react";
const DashboardContext = createContext(null);
export function DashboardProvider({ children }) {
const [filters, setFilters] = useState({ date: "today" });
return (
<DashboardContext.Provider value={{ filters, setFilters }}>
{children}
</DashboardContext.Provider>
);
}
export function useDashboard() {
const context = useContext(DashboardContext);
if (!context) throw new Error("useDashboard must be used within DashboardProvider");
return context;
}
Side effects with useEffect:
import { useEffect, useState } from "react";
export default function Component() {
const [data, setData] = useState([]);
useEffect(() => {
// Fetch data
async function fetchData() {
const response = await fetch("/api/data");
const result = await response.json();
setData(result);
}
fetchData();
}, []); // Empty array = run once on mount
return <div>{/* Render data */}</div>;
}
Optimizing state updates:
// Functional updates when new state depends on old state
setCount(prevCount => prevCount + 1);
// Batch updates (automatic in React 18+)
setCount(count + 1);
setLoading(false);
// Both updates batched together
Form state management:
import { useState } from "react";
export default function Form() {
const [formData, setFormData] = useState({
name: "",
email: "",
});
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value,
});
};
const handleSubmit = (e) => {
e.preventDefault();
// Process formData
};
return (
<form onSubmit={handleSubmit}>
<input
name="name"
value={formData.name}
onChange={handleChange}
/>
<input
name="email"
value={formData.email}
onChange={handleChange}
/>
<button type="submit">Submit</button>
</form>
);
}
Avoid common pitfalls:
"use client";
import { useState } from "react";
export default function Dashboard() {
const [dateRange, setDateRange] = useState("last7days");
const [chartType, setChartType] = useState("line");
// Filtered data derived from state
const filteredData = data.filter(item =>
filterByDateRange(item, dateRange)
);
return (
<div>
<select
value={dateRange}
onChange={(e) => setDateRange(e.target.value)}
>
<option value="last7days">Last 7 Days</option>
<option value="last30days">Last 30 Days</option>
</select>
<DashboardCharts data={filteredData} type={chartType} />
</div>
);
}
// hooks/useStats.ts
import { useState, useEffect } from "react";
export function useStats() {
const [stats, setStats] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchStats() {
try {
const response = await fetch("/api/stats");
const data = await response.json();
setStats(data);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
}
fetchStats();
}, []);
return { stats, loading, error };
}
// Usage in component
function Dashboard() {
const { stats, loading, error } = useStats();
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{/* Render stats */}</div>;
}
// This project uses next-themes for theme management
"use client";
import { useTheme } from "next-themes";
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
return (
<button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
Toggle Theme
</button>
);
}
src/components/theme-provider.tsxsrc/components/DashboardCharts.tsxsrc/components/LayoutWrapper.tsxoptimize-react-componentdebug-componentcreate-dashboard-page