Motty
터미널·SFTP·포트 포워딩·VNC·RDP·AI 도우미를 하나의 창에 통합, Go 기반 무료 오픈소스
AI 코딩 에이전트를 위한 React 상태 관리. 에이전트가 구조화·테스트 가능한 코드를 작성하고 린터가 검증합니다
React state management, built for AI coding agents. Your agent writes structured, testable code, and a linter checks its work. You can still read every line.
개발 도구TypeScript · GherkinGitHub @marcglasberg온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
Powerful State Management for React and React Native. Docs: https://kissforreact.org
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Kiss helps AI agents stay on track, session after session, while spending fewer tokens.
npm install kiss-for-react
The store holds all application state. Here are a few examples:
// Your state is a number
const store = createStore<number>({initialState: 1});
// Your state is a plain JavaScript object
const store = createStore({initialState: {name: 'Mary', age: 25}});
// Your state is an instance of an ES6 class
class State { constructor(public name: string, public age: number){} }
const store = createStore<State>({initialState: new State('Mary', 25)});
Use a StoreProvider to add the store to your component tree:
function App() {
return (
<StoreProvider store={store}>
<AppContent />
</StoreProvider>
);
};
The useAllState hook lets you access the whole state from any component.
The component re-renders when any part of the state changes (not recommended, but good for
fast prototyping).
function MyComponent() {
const state = useAllState<State>();
return <div>{state.name} is {state.age} years old</div>;
};
The useSelect hook selects only the part of the state that your component needs.
The component re-renders only when that part changes.
function MyComponent() {
const name = useSelect((state: State) => state.name);
const age = useSelect((state: State) => state.age);
return <div>{name} is {age} years old</div>;
};
The useObject hook also causes the component to re-render only when needed:
function MyComponent() {
const state = useObject((state: State) => ({
name: state.name,
age: state.age,
}));
return <div>{state.name} is {state.age} years old</div>;
};
These hooks connect to the store with React's own
useSyncExternalStore,
so React reads the state itself, compares what each component selected, and renders only
the components whose selection changed. React also checks the state again before
committing a
render it paused (a transition), and renders again if the state changed meanwhile, so a
screen never shows parts of two different states at the same time.
An action is a class with its own reducer function. This reducer has access to the current state and returns a new state.
class Increment extends Action {
reduce() {
// The reducer has access to the current state
return this.state + 1; // It returns a new state
};
}
The store's state is immutable.
The only way to change the store's state is by dispatching an action, wich runs the action's reducer to get a new state. The new state replaces the current one, and affected components re-render.
// Dispatch an action
store.dispatch(new Increment());
// Dispatch multiple actions
store.dispatchAll([new Increment(), new LoadText()]);
// Dispatch an action and wait for it to finish
await store.dispatchAndWait(new Increment());
// Dispatch multiple actions and wait for them to finish
await store.dispatchAndWaitAll([new Increment(), new LoadText()]);
// Dispatch an action when the state meets a condition
store.dispatchWhen(new LoadText(), (state) => state.count >= 3);
Hooks for dispatching actions include useDispatch, useDispatchAll, useDispatchWhen,
etc.
function MyComponent() {
const dispatch = useDispatch();
return (
<Button onClick={() => dispatch(new LoadText())}>
Click me!
</Button>
);
};
You can also get the store with useStore and dispatch actions directly:
function MyComponent() {
const store = useStore();
return (
<Button onClick={() => store.dispatch(new LoadText())}>
Click me!
</Button>
);
};
To dispatch actions when the component mounts, when some values change, and when it
unmounts,
use useStoreEffect instead of a useEffect:
useStoreEffect({
deps: userId, // List the dependencies
// Loads information needed for this screen
onMount: (store) => store.dispatch(new LoadUser(userId)),
// When the userId changes, stop listening to the old user and load the new one
onDepsChange: (store, oldUserId) => {
store.dispatch(new StopListening(oldUserId));
store.dispatch(new LoadUser(userId));
},
// When the component unmounts, clean up any resources used by this screen
onUnmount: (store) => store.dispatch(new CleanResources()),
});
To reload the data on screen when the user comes back to the browser tab, or when the
internet
comes back, add onFocus and onOnline (there are also onBlur and onOffline). They
run
only on the transitions, while the component is mounted, never on mount. Give the action a
fresh period to skip the reload when the data is recent:
useStoreEffect({
onMount: (store) => store.dispatch(new LoadPrices()),
onFocus: (store) => store.dispatch(new LoadPrices()),
onOnline: (store) => store.dispatch(new LoadPrices()),
});
Also available in components with useIsFocused() and useIsOnline(),
for an "offline" banner.
Actions can fetch data from the internet or do any other async work.
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗