Keep domain state where it belongs, but make UI components boring to mount. Screens compose containers. Containers call hooks.
Components receive explicit props and callbacks.
Screennavigation, layout, feature composition
→
Container / hookZustand, React Query, SecureStore, API client
→
View componentprops only, Storybook args, unit tests
src/features/counter/
counter.store.ts # Zustand lives here
useCounterModel.ts # maps store/actions into UI contract
CounterContainer.tsx # app adapter
CounterView.tsx # pure UI
CounterView.stories.tsx # args-only Storybook story
CounterView.unit.test.tsx # optional UI behavior tests
Container
export function CounterContainer() {
const count = useCounterStore((s) => s.count)
const increment = useCounterStore((s) => s.increment)
return (
<CounterView
count={count}
onIncrement={increment}
/>
)
}
Story
export default {
title: 'features/counter/CounterView',
component: CounterView,
}
export const Default = {
args: {
count: 7,
onIncrement: fn(),
},
}