https://github.com/js2me/mobx-react-routing
https://github.com/js2me/mobx-react-routing
Last synced: 8 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/js2me/mobx-react-routing
- Owner: js2me
- License: mit
- Created: 2024-07-19T19:48:31.000Z (almost 2 years ago)
- Default Branch: master
- Last Pushed: 2025-09-03T20:03:56.000Z (10 months ago)
- Last Synced: 2025-10-06T20:50:01.537Z (8 months ago)
- Language: TypeScript
- Size: 692 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# mobx-react-routing
## Usage (with using `rootStore`)
> requires `mobx-view-model` package usage
### 1. Create `PageViewModelImpl` class
This class you will needed for creating your own view model classes
You can implement your own solution based on `PageViewModel` interface, but `PageViewModelBase` has a lot of ready solutions like `queryParams` or `pathParams`
Only one thing that you should implement is the `getParentViewModel` and `constructor` because it requires (in most cases) `RootStore`
```tsx
import { PageViewModelBase, RouteDeclaration, RouterStore } from 'mobx-react-routing';
import { ViewModel } from 'mobx-view-model';
export class PageViewModelImpl<
Params extends AnyObject = EmptyObject,
ParentViewModel extends ViewModel | null = null,
>
extends PageViewModelBase
{
protected router: RouterStore;
constructor(
protected rootStore: RootStore,
routeDeclaration: RouteDeclaration,
config: ViewModelParams,
) {
super(routeDeclaration, rootStore.router, config);
this.router = rootStore.router;
}
yourMethodForAllVMs() {
console.info('log')
}
}
```
### 2. Create `RouterStoreImpl` Class
This class will contains info about all routing and will have all router utilities based on `react-router-dom`.
You can implement your own solution based on `RouterStore` interface, but `RouterStoreBase` has a lot of ready solutions like `navigate`, `blockRoutingIf`, `blockRouting` etc.
```tsx
import {
RouterStoreBase,
RouterStoreParams,
RouteDeclaration,
CreateRouteViewModelFactory,
createRoute,
} from 'mobx-react-routing';
import { RouteObject } from 'react-router-dom';
import { PageViewModelImpl } from './page-view-model';
export class RouterStoreImpl extends RouterStoreBase {
constructor(
protected rootStore: RootStore,
params: RouterStoreParams,
) {
super(params);
}
// override this method because we need to send rootStore to our view models
// but default `RouterStoreBase` this method implementation don't know about RootStore
createRoute(
declaration: RouteDeclaration,
index: number,
parentPath: number[],
): RouteObject {
const createViewModel: CreateRouteViewModelFactory = (
config,
declaration,
) => {
const VM = config.VM as unknown as typeof PageViewModelImpl;
return new VM(this.rootStore, declaration, config);
};
return createRoute({
declaration,
router: this,
index,
parentPath,
factory: createViewModel,
});
}
}
```
### 3. create instance of your `RouterStore` implementation
```tsx
import { Outlet } from "react-router-dom"
const routerStore = new RouterStoreImpl(rootStore, {
routes: [
{
path: '/',
element: () => ,
children: [
{
index: true,
async loader() {
const { HomePage, HomePageModel } = await import('@/pages/home');
return {
Component: HomePage,
Model: HomePageModel,
};
},
},
{
path: '/my-page',
async loader() {
const { MyPagePage, MyPagePageModel } = await import('@/pages/my-page');
return {
Component: MyPagePage,
Model: MyPagePageModel,
};
},
}
]
},
{
path: '/login',
async loader() {
const { LoginPage, LoginPageModel } = await import('@/pages/login');
return {
Component: LoginPage,
Model: LoginPageModel,
};
},
},
{
path: '*',
Model: NotFoundPageModel,
},
],
fallbackComponent: () => null,
errorBoundaryComponent: () => null,
});
```
### 4. Attach instance to rootStore
```ts
rootStore.router = routerStore;
```
### 5. Create Page view model and view
```tsx
export class HomePageVM extends PageViewModelImpl<{ bar?: string }> {
mount(): void {
super.mount();
}
unmount(): void {
super.unmount();
}
didUnmount(): void {
// cleanup here
}
}
export const HomePageView = observer(({ model }: ViewModelProps) => {
return (
{`foo query param - ${model.queryParams.foo}`}
{`bar path param - ${model.pathParams.bar}`}
)
})
```
### About path params
Path params should be declared in route declaration firstly
```ts
import { RouteDeclaration } from 'mobx-react-routing';
const routeDeclaration: RouteDeclaration = {
errorBoundary: ErrorBoundary,
fallback: GlobalLoader,
path: '/my-page/:barId',
async loader() {
const { HomePageModel } = await import('@/pages/home');
return {
Model: HomePageModel,
};
},
}
```
Here is `:barId` is string path param with key `barId`. Then in your VM you can declare it using generic
```ts
export class HomePageVM extends PageViewModelImpl<{ barId: string }> {
bars = [
{
id: 'kek',
name: 'Kek',
},
{
id: 'pek',
name: 'Pek',
},
]
get barData(){
return this.bars.find(it => it.id === this.pathParams.barId)
}
}
```