Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/CodySwannGT/lisa --skill local-stateコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
This skill should be used for any non-trivial request — features, bugs, stories, epics, spikes, or multi-step tasks. It accepts a ticket URL (Jira, Linear, GitHub), a file path containing a spec, or a plain-text prompt. It assembles an agent team, breaks the work into structured tasks, and manages the full lifecycle from research through implementation, code review, deploy, and empirical verification.
any non-trivial request —…
This skill should be used for any non-trivial request — features, bugs, stories, epics, spikes, or multi-step tasks. It accepts a ticket URL (Jira, Linear, GitHub), a file path containing a spec, or a plain-text prompt. It assembles an agent team, breaks the work into structured tasks, and manages the full lifecycle from research through implementation, code review, deploy, and empirical verification.
SOC 職業分類に基づく
SKILL.md を表示中
| name | local-state |
| description | implementing local state… |
This skill provides best practices for local state management in this React Native/Expo codebase. Local state is managed using two complementary approaches:
| Use Case | Approach | Example |
|---|---|---|
| UI state that resets on refresh | Reactive Variable only | Modal open state, form drafts |
| User preferences that persist | Reactive Variable + AsyncStorage | Theme, language, notifications |
| Feature flags | Reactive Variable + AsyncStorage | Beta features, profiler toggle |
| Session-scoped data | Reactive Variable only | Current filter selections |
| Cross-component communication | Reactive Variable | Selected player ID, active tab |
| Authentication tokens | expo-secure-store | Access tokens, refresh tokens |
import { makeVar } from "@apollo/client";
interface IUserPreferences {
readonly theme: "light" | "dark";
readonly notifications: boolean;
}
const DEFAULT_PREFERENCES: IUserPreferences = {
theme: "light",
notifications: true,
};
export const userPreferencesVar =
makeVar<IUserPreferences>(DEFAULT_PREFERENCES);
import { useReactiveVar } from "@apollo/client";
const MyComponent = () => {
const preferences = useReactiveVar(userPreferencesVar);
return <Text>{preferences.theme}</Text>;
};
// Update with new object reference
userPreferencesVar({
...userPreferencesVar(),
theme: "dark",
});
import AsyncStorage from "@react-native-async-storage/async-storage";
const STORAGE_KEY = "@whatever:user-preferences";
export const savePreferences = async (
prefs: IUserPreferences
): Promise<void> => {
userPreferencesVar(prefs); // Update reactive variable first
try {
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(prefs));
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error";
console.error("Failed to save preferences:", message);
}
};
export const loadPreferences = async (): Promise<void> => {
try {
const stored = await AsyncStorage.getItem(STORAGE_KEY);
if (stored) {
const parsed = JSON.parse(stored) as ;
({ ..., ...parsed });
}
} (error) {
message = error ? error. : ;
.(, message);
}
};
Never mutate existing objects or arrays. Create new references to trigger reactivity:
// CORRECT - creates new object
userPreferencesVar({
...userPreferencesVar(),
theme: "dark",
});
// INCORRECT - mutation does NOT trigger updates
const prefs = userPreferencesVar();
prefs.theme = "dark"; // This does nothing!
userPreferencesVar(prefs); // Same reference, no update
useReactiveVar for Reactive ComponentsCalling myVar() directly does NOT trigger re-renders. Always use the hook:
// CORRECT - component re-renders when variable changes
const theme = useReactiveVar(themeVar);
// INCORRECT - no re-renders on variable change
const theme = themeVar();
Create custom hooks for testability and encapsulation:
export const useTheme = () => {
const preferences = useReactiveVar(userPreferencesVar);
const setTheme = useCallback((theme: "light" | "dark") => {
savePreferences({ ...userPreferencesVar(), theme });
}, []);
return { theme: preferences.theme, setTheme };
};
Prefix all AsyncStorage keys with the app namespace:
// CORRECT
const STORAGE_KEY = "@whatever:filter-values";
// INCORRECT - collision risk
const STORAGE_KEY = "filters";
AsyncStorage operations can fail. Always use try/catch:
// CORRECT
try {
await AsyncStorage.setItem(key, JSON.stringify(value));
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error";
console.error(`Failed to save ${key}:`, message);
}
// INCORRECT - silent failures
await AsyncStorage.setItem(key, JSON.stringify(value));
AsyncStorage is unencrypted. Use expo-secure-store for sensitive data:
// CORRECT - use secure store for tokens
import * as SecureStore from "expo-secure-store";
await SecureStore.setItemAsync("accessToken", token);
// INCORRECT - never store tokens in AsyncStorage
await AsyncStorage.setItem("accessToken", token);
Initialize persisted state early in the app lifecycle:
// In root layout or app initialization
useEffect(() => {
loadPreferences();
}, []);
Organize reactive variables and persistence logic in dedicated store files:
features/
my-feature/
stores/
featureState.ts # Reactive variable + persistence logic
index.ts # Re-exports
Example store file structure:
// stores/userPreferences.ts
import { makeVar, useReactiveVar } from "@apollo/client";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { useCallback } from "react";
// Types
interface IUserPreferences {
readonly theme: "light" | "dark";
readonly language: string;
}
// Constants
const STORAGE_KEY = "@whatever:user-preferences";
const DEFAULT_PREFERENCES: IUserPreferences = {
theme: "light",
language: "en",
};
// Reactive Variable
export const userPreferencesVar =
makeVar<IUserPreferences>(DEFAULT_PREFERENCES);
// Persistence Functions
export const loadUserPreferences = async (): Promise<void> => {
try {
const stored = await AsyncStorage.getItem(STORAGE_KEY);
if (stored) {
parsed = .(stored) ;
({ ..., ...parsed });
}
} (error) {
message = error ? error. : ;
.(, message);
}
};
saveUserPreferences = (: ): <> => {
(prefs);
{
.(, .(prefs));
} (error) {
message = error ? error. : ;
.(, message);
}
};
= () => {
preferences = (userPreferencesVar);
setTheme = ( {
({ ...(), theme });
}, []);
setLanguage = ( {
({ ...(), language });
}, []);
{ preferences, setTheme, setLanguage };
};
For comprehensive patterns and examples, see the reference files:
// WRONG - mutation
const filters = filtersVar();
filters.minAge = 25;
filtersVar(filters);
// CORRECT - new reference
filtersVar({ ...filtersVar(), minAge: 25 });
localStorage in React Native// WRONG - doesn't exist in React Native
localStorage.setItem("key", value);
// CORRECT - use AsyncStorage
await AsyncStorage.setItem("key", value);
myVar() expecting re-renders// WRONG - no reactivity
const Component = () => {
const value = myVar(); // Does NOT trigger re-renders
return <Text>{value}</Text>;
};
// CORRECT - reactive
const Component = () => {
const value = useReactiveVar(myVar);
return <Text>{value}</Text>;
};
// WRONG - AsyncStorage only accepts strings
await AsyncStorage.setItem("key", { name: "John" });
// CORRECT - serialize first
await AsyncStorage.setItem("key", JSON.stringify({ name: "John" }));
// WRONG - state resets on app restart
export const filtersVar = makeVar<Filters>(DEFAULT_FILTERS);
// CORRECT - load on app start
export const filtersVar = makeVar<Filters>(DEFAULT_FILTERS);
export const loadFilters = async () => {
/* ... */
};
// Call loadFilters() in app initialization
When writing or reviewing local state code, verify:
makeVar<Type>(default)useReactiveVar() hook, not direct myVar() calls@whatever:expo-secure-store, not AsyncStoragestores/ directory