Skip to content

Commit

Permalink
feat: new extension vike-react-redux
Browse files Browse the repository at this point in the history
  • Loading branch information
phonzammi committed Jan 27, 2025
1 parent 2fbbe61 commit d1198b3
Show file tree
Hide file tree
Showing 11 changed files with 428 additions and 12 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"vike-react-chakra": "link:./packages/vike-react-chakra/",
"vike-react-antd": "link:./packages/vike-react-antd/",
"vike-react-styled-components": "link:./packages/vike-react-styled-components/",
"vike-react-styled-jsx": "link:./packages/vike-react-styled-jsx/"
"vike-react-styled-jsx": "link:./packages/vike-react-styled-jsx/",
"vike-react-redux": "link:./packages/vike-react-redux/"
}
},
"devDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions packages/vike-react-redux/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules/
/dist/
123 changes: 123 additions & 0 deletions packages/vike-react-redux/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# `vike-react-redux`

Integrates [React Redux](https://react-redux.js.org) to your [`vike-react`](https://vike.dev/vike-react) app.

[Installation](#installation)
[Settings](#settings)
[Version history](https://github.com/vikejs/vike-react/blob/main/packages/vike-react-redux/CHANGELOG.md)
[What it does](#what-it-does)
[See Also](#see-also)

<br/>

## Installation

1. `npm install vike-react-redux react-redux @reduxjs/toolkit`
2. Extend `+config.js`:
```js
// pages/+config.js

import vikeReact from "vike-react/config"
import vikeReactRedux from "vike-react-redux/config"

export default {
// ...
extends: [vikeReact, vikeReactRedux]
}
```

3. Create `+redux.ts` file with the following code format/example:
```ts
export { redux }

// Create and import your reducers
import counterReducer from "../lib/features/counter/counterSlice";
import { combineReducers, configureStore } from "@reduxjs/toolkit";

const rootReducer = combineReducers({ counter: counterReducer });

const redux = {
createStore: (preloadedState: any) => {
return configureStore({
reducer: rootReducer,
preloadedState
})
}
}

// Infer the type of redux.createStore
export type AppStore = ReturnType<typeof redux.createStore>;
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<AppStore["getState"]>;
// Infer the `AppDispatch` type from the store itself
export type AppDispatch = AppStore["dispatch"];
```

4. Update your `global.d.ts` like the following (optional):
```ts
import { AppStore, RootState } from "./pages/+redux";

declare global {
namespace Vike {
interface PageContext {
redux?: {
state?: RootState;
};
}
interface Config {
redux?: {
createStore?: (preloadedState?: any) => AppStore;
store?: AppStore;
};
}
}
}

export {};
```
5. You can now use React Redux at any of your components.
```tsx
import React from "react"
import { increment, selectCount } from "../../lib/features/counter/counterSlice"
import { useDispatch, useSelector } from "react-redux"
import type { AppDispatch } from "../+redux"

export function Counter() {
const dispatch = useDispatch<AppDispatch>()
const count = useSelector(selectCount)

return (
<button type="button" onClick={() => dispatch(increment())}>
Counter {count}
</button>
)
}
```

<br/>

## Settings
You can remove the `vike-react-redux` integration from [some of your pages](https://vike.dev/config#inheritance):

```js
// pages/about/+redux.js

export const redux = null
```

For full customization consider [ejecting](https://vike.dev/eject).

> [!NOTE]
> Consider making a [Pull Request before ejecting](https://vike.dev/eject#when-to-eject).
<br/>

## What it does
TODO

<br/>

## See also
- [Vike Docs > Redux](https://vike.dev/redux)
- [Vike Docs > Store](https://vike.dev/store)
- [React Redux](https://react-redux.js.org)
23 changes: 23 additions & 0 deletions packages/vike-react-redux/Wrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export { Wrapper }

import React, { useRef } from 'react'
import { Provider } from 'react-redux'
import { usePageContext } from 'vike-react/usePageContext'
import type { Store } from '@reduxjs/toolkit'

function Wrapper({ children }: { children: React.ReactNode }) {
const pageContext = usePageContext()
const { redux } = pageContext.config
const storeRef = useRef<Store>()

if (!redux) {
return <>{children}</>
}

if (!storeRef.current) {
// Create the store instance the first time this renders
storeRef.current = redux.store
}

return <Provider store={storeRef.current!}>{children}</Provider>
}
37 changes: 37 additions & 0 deletions packages/vike-react-redux/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export { config as default }
import type { Config } from 'vike/types'
import type { Store } from '@reduxjs/toolkit'

const config = {
name: 'vike-react-redux',
require: {
vike: '>=0.4.211',
'vike-react': '>=0.4.13',
},
passToClient: ['redux'],
onAfterRenderHtml: 'import:vike-react-redux/__internal/onAfterRenderHtml:onAfterRenderHtml',
onBeforeRenderHtml: 'import:vike-react-redux/__internal/onBeforeRenderHtml:onBeforeRenderHtml',
onBeforeRenderClient: 'import:vike-react-redux/__internal/onBeforeRenderClient:onBeforeRenderClient',
Wrapper: 'import:vike-react-redux/__internal/Wrapper:Wrapper',
meta: {
redux: {
env: { server: true, client: true },
},
},
} satisfies Config

declare global {
namespace Vike {
interface PageContext {
redux?: {
state?: unknown
}
}
interface Config {
redux?: null | {
createStore?: (preloadedState?: any) => Store
store?: Store
}
}
}
}
13 changes: 13 additions & 0 deletions packages/vike-react-redux/onAfterRenderHtml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export { onAfterRenderHtml }

import { PageContext } from 'vike/types'

function onAfterRenderHtml(pageContext: PageContext) {
if (pageContext.config.redux?.store) {
const store = pageContext.config.redux.store

pageContext.redux ??= {
state: store?.getState(),
}
}
}
12 changes: 12 additions & 0 deletions packages/vike-react-redux/onBeforeRenderClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export { onBeforeRenderClient }

import { PageContext } from 'vike/types'

function onBeforeRenderClient(pageContext: PageContext) {
if (pageContext.config.redux) {
const createStore = pageContext.config.redux.createStore
if (createStore) {
pageContext.config.redux.store = createStore(pageContext.redux?.state)
}
}
}
12 changes: 12 additions & 0 deletions packages/vike-react-redux/onBeforeRenderHtml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export { onBeforeRenderHtml }

import { PageContext } from 'vike/types'

function onBeforeRenderHtml(pageContext: PageContext) {
if (pageContext.config.redux) {
const createStore = pageContext.config.redux.createStore
if (createStore) {
pageContext.config.redux.store = createStore()
}
}
}
63 changes: 63 additions & 0 deletions packages/vike-react-redux/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"name": "vike-react-redux",
"version": "0.0.0",
"type": "module",
"exports": {
"./config": "./dist/config.js",
"./__internal/onAfterRenderHtml": "./dist/onAfterRenderHtml.js",
"./__internal/onBeforeRenderHtml": "./dist/onBeforeRenderHtml.js",
"./__internal/onBeforeRenderClient": "./dist/onBeforeRenderClient.js",
"./__internal/Wrapper": "./dist/Wrapper.js"
},
"scripts": {
"dev": "tsc --watch",
"build": "rimraf dist/ && tsc",
"release": "release-me patch",
"release:minor": "release-me minor",
"release:major": "release-me major",
"release:commit": "release-me commit"
},
"peerDependencies": {
"@reduxjs/toolkit": ">=2",
"react-redux": ">=9",
"react": ">=18",
"vike-react": ">=0.4.13"
},
"devDependencies": {
"@brillout/release-me": "^0.4.2",
"@reduxjs/toolkit": "^2.5.0",
"@types/react": "^18.2.55",
"react": "^18.3.1",
"react-redux": "^9.2.0",
"rimraf": "^5.0.5",
"typescript": "^5.5.3",
"vike": "^0.4.211",
"vike-react": "^0.5.12",
"vite": "^5.4.0"
},
"typesVersions": {
"*": {
"config": [
"dist/config.d.ts"
],
"__internal/onAfterRenderHtml": [
"dist/onAfterRenderHtml.d.ts"
],
"__internal/onBeforeRenderHtml": [
"dist/onBeforeRenderHtml.d.ts"
],
"__internal/onBeforeRenderClient": [
"dist/onBeforeRenderClient.d.ts"
],
"__internal/Wrapper": [
"dist/Wrapper.d.ts"
]
}
},
"files": [
"dist"
],
"repository": "https://github.com/vikejs/vike-react/tree/main/packages/vike-react-redux",
"license": "MIT"
}

16 changes: 16 additions & 0 deletions packages/vike-react-redux/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"declaration": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"jsx": "react",
"outDir": "./dist/",
"skipLibCheck": true,
"types": ["vike-react"],
// Strictness
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitAny": true
}
}
Loading

0 comments on commit d1198b3

Please sign in to comment.