#Frontend

Snapstate: Separating Business Logic from React Components

Startups Reporter
3 min read

Thales Bruno's Snapstate offers a new approach to state management by moving business logic out of React components and into plain TypeScript classes, creating clearer boundaries between UI and application logic.

React has become the go-to library for building user interfaces, but as applications grow, developers often face challenges when application logic becomes intertwined with UI components. Thales Bruno, a developer with experience in complex React applications, created Snapstate as a solution to this common problem.

The core issue Bruno identified is that many React applications gradually drift into similar patterns: data fetching in useEffect hooks, business rules inside custom hooks, derived values spread across useMemo, and mutations hidden in event handlers. While this approach works, it creates blurry boundaries between UI and application logic, making code harder to test and reuse.

"React is excellent at rendering UI. It's less convincing as the place where the rest of the app should live," Bruno explains in his blog post announcing Snapstate. This observation led him to develop a solution that maintains React's strengths while providing a cleaner separation of concerns.

Snapstate introduces class-based stores that contain application logic, while React components remain focused solely on rendering. This approach allows developers to test business logic without React infrastructure, creates components that only render, and establishes a clearer boundary between UI and application logic.

In his post, Bruno contrasts traditional React state management with the Snapstate approach. He provides a detailed example of a dashboard component that handles authentication, data fetching, loading states, error handling, derived values, and mutations—all within the component itself. With Snapstate, these responsibilities move to dedicated stores, leaving the component as a simple rendering function.

The solution isn't without tradeoffs. Bruno specifically built Snapstate because existing options didn't offer the balance he wanted. Redux, while predictable, introduces too much ceremony for many applications. Zustand is lighter but remains hook-centric. MobX comes closest to his vision but relies on "implicit proxy tracking" which he found too magical.

"Snapstate is my attempt at that middle ground: class-based stores, explicit updates, and React as an adapter instead of the place where the business logic lives," Bruno explains.

One significant advantage of this approach is simplified testing. When business logic lives in plain TypeScript classes, developers can exercise it directly without render harnesses, providers, or waiting for UI state. Bruno provides a clear example of how testing a notification marking feature becomes straightforward with Snapstate.

The project has evolved beyond the core concept to include additional features like scoped stores for per-screen lifecycle, form stores with Zod validation, and URL synchronization. However, Bruno emphasizes that these features are consequences of the original design principle rather than the primary motivation.

"The reason was much simpler: I wanted business logic to live in plain TypeScript, and I wanted React to go back to being the rendering layer," Bruno states.

Snapstate is available as an open-source project on GitHub and can be installed via npm. While Bruno still considers it alpha due to ongoing development, the core API has proven stable in production environments. The project represents an interesting addition to the React ecosystem, particularly for developers who have struggled with the growing complexity of state management in larger applications.

For developers interested in exploring this approach, Snapstate's documentation and example app provide practical implementation guidance. The project's GitHub repository offers the complete source code and additional examples of how to apply the pattern in different scenarios.

As the React ecosystem continues to evolve, solutions like Snapstate highlight the ongoing tension between framework capabilities and application architecture needs. By providing a clear separation between UI rendering and business logic, Snapstate offers developers another option for building maintainable, testable React applications.

Comments

Loading comments...