Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/atomic-router/atomic-router
Platform-agnostic router that does not break your architecture
https://github.com/atomic-router/atomic-router
atomic-router effector forest javascript js router routing solid solidjs ts typescript
Last synced: about 3 hours ago
JSON representation
Platform-agnostic router that does not break your architecture
- Host: GitHub
- URL: https://github.com/atomic-router/atomic-router
- Owner: atomic-router
- License: mit
- Created: 2021-10-26T00:11:40.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-02-13T14:19:36.000Z (9 months ago)
- Last Synced: 2024-04-14T06:47:32.421Z (7 months ago)
- Topics: atomic-router, effector, forest, javascript, js, router, routing, solid, solidjs, ts, typescript
- Language: TypeScript
- Homepage: https://atomic-router.github.io
- Size: 1.69 MB
- Stars: 138
- Watchers: 4
- Forks: 16
- Open Issues: 24
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# Atomic Router
Simple routing implementation that provides abstraction layer instead of inline URL's and does not break your architecture
- Type-safe
- No inline URL's
- Atomic routes
- Does not break architecture
- Framework-agnostic
- Isomorphic (pass your own `history` instance and it works everywhere)### Read the docs: [atomic-router.github.io](https://atomic-router.github.io)
> โ๏ธ **Attention**: At the moment atomic-router team collecting issues and feature requests to improve current design. Upgrade atomic-router version with caution. We are going to write migration guide when/if the release will contain breaking changes. Thank you for reporting issues ๐งก
### Get view-library bindings
- โ๏ธ [**React**](https://github.com/atomic-router/react)
- ๐ [**Forest**](https://github.com/atomic-router/forest)
- [**Solid**](https://github.com/atomic-router/solid)## Installation
```bash
$ npm install effector atomic-router
```## Initialization
Create your routes wherever you want:
```ts
// pages/home
import { createRoute } from 'atomic-router';
export const homeRoute = createRoute();// pages/posts
import { createRoute } from 'atomic-router';
export const postsRoute = createRoute<{ postId: string }>();
```And then create a router
```ts
// app/routing
import { createHistoryRouter } from 'atomic-router';
import { createBrowserHistory, createMemoryHistory } from 'history';
import { homeRoute } from '@/pages/home';
import { postsRoute } from '@/pages/posts';const routes = [
{ path: '/', route: homeRoute },
{ path: '/posts', route: postsRoute },
];const router = createHistoryRouter({
routes: routes,
});// Attach history
const history = isSsr ? createMemoryHistory() : createBrowserHistory();
router.setHistory(history);
```## Why atomic routes?
There are 3 purposes for using atomic routes:
- To abstract the application from hard-coded paths
- To provide you a declarative API for a comfortable work
- To avoid extra responsibility in app features## Examples
Fetch post on page open
1. In your model, create effect and store which you'd like to trigger:
```tsx
export const getPostFx = createEffect<{ postId: string }, Post>(
({ postId }) => {
return api.get(`/posts/${postId}`);
}
);export const $post = restore(getPostFx.doneData, null);
```2. And just trigger it when `postPage.$params` change:
```tsx
//route.ts
import { createRoute } from 'atomic-router';
import { getPostFx } from './model';const postPage = createRoute<{ postId: string }>();
sample({
source: postPage.$params,
filter: postPage.$isOpened,
target: getPostFx,
});
```Avoid breaking architecture
Imagine that we have a good architecture, where our code can be presented as a dependency tree.
So, we don't make neither circular imports, nor they go backwards.
For example, we have `Card -> PostCard -> PostsList -> PostsPage` flow, where `PostsList` doesn't know about `PostsPage`, `PostCard` doesn't know about `PostsList` etc.But now we need our `PostCard` to open `PostsPage` route.
And usually, we add extra responisbility by letting it know what the route is```tsx
const PostCard = ({ id }) => {
const post = usePost(id);return (
{post.title}
{post.title}
{/* NOOOO! */}
Read More
);
};
```With `atomic-router`, you can create a "personal" route for this card:
```tsx
const readMoreRoute = createRoute<{ postId: id }>();
```And then you can just give it the same path as your `PostsPage` has:
```tsx
const routes = [
{ path: '/posts/:postId', route: readMoreRoute },
{ path: '/posts/:postId', route: postsPageRoute },
];
```Both will work perfectly fine as they are completely independent
## API Reference
```tsx
// Params is an object-type describing query params for your route
const route = createRoute();// Stores
route.$isOpened; // Store
route.$params; // Store<{ [key]: string }>
route.$query; // Store<{ [key]: string }>// Events (only watch 'em)
route.opened; // Event<{ params: RouteParams, query: RouteQuery }>
route.updated; // Event<{ params: RouteParams, query: RouteQuery }>
route.closed; // Event<{ params: RouteParams, query: RouteQuery }>// Effects
route.open; // Effect
route.navigate; // Effect<{ params: RouteParams, query: RouteQuery }>// Note: Store, Event and Effect is imported from 'effector' package
```