Skip to content

Commit

Permalink
add example
Browse files Browse the repository at this point in the history
  • Loading branch information
phonzammi committed Jan 31, 2025
1 parent 44d01a5 commit 418fa29
Show file tree
Hide file tree
Showing 19 changed files with 398 additions and 0 deletions.
2 changes: 2 additions & 0 deletions examples/redux/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules/
/dist/
36 changes: 36 additions & 0 deletions examples/redux/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions examples/redux/components/Counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'
import { useAppDispatch, useAppSelector } from '../lib/hooks'
import { increment, selectCount } from '../lib/features/counter/counterSlice'

export function Counter() {
const dispatch = useAppDispatch()
const count = useAppSelector(selectCount)

return (
<button type="button" onClick={() => dispatch(increment())}>
Counter {count}
</button>
)
}
15 changes: 15 additions & 0 deletions examples/redux/components/Link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export { Link }

import { usePageContext } from 'vike-react/usePageContext'
import React from 'react'

function Link({ href, children }: { href: string; children: string }) {
const pageContext = usePageContext()
const { urlPathname } = pageContext
const isActive = href === '/' ? urlPathname === href : urlPathname.startsWith(href)
return (
<a href={href} className={isActive ? 'is-active' : undefined}>
{children}
</a>
)
}
12 changes: 12 additions & 0 deletions examples/redux/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { AppStore, RootState } from './pages/+redux'

declare global {
namespace Vike {
interface PageContext {
reduxState?: RootState
reduxStore?: AppStore
}
}
}

export {}
14 changes: 14 additions & 0 deletions examples/redux/layouts/HeadDefault.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default HeadDefault

import React from 'react'
import logoUrl from '../assets/logo.svg'

function HeadDefault() {
return (
<>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Demo showcasing Vike + React" />
<link rel="icon" href={logoUrl} />
</>
)
}
75 changes: 75 additions & 0 deletions examples/redux/layouts/LayoutDefault.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
export default LayoutDefault

import './style.css'
import React from 'react'
import logoUrl from '../assets/logo.svg'
import { Link } from '../components/Link'

function LayoutDefault({ children }: { children: React.ReactNode }) {
return (
<div
style={{
display: 'flex',
maxWidth: 900,
margin: 'auto',
}}
>
<Sidebar>
<Logo />
<Link href="/">Welcome</Link>
<Link href="/about">About</Link>
</Sidebar>
<Content>{children}</Content>
</div>
)
}

function Sidebar({ children }: { children: React.ReactNode }) {
return (
<div
id="sidebar"
style={{
padding: 20,
flexShrink: 0,
display: 'flex',
flexDirection: 'column',
lineHeight: '1.8em',
borderRight: '2px solid #eee',
}}
>
{children}
</div>
)
}

function Content({ children }: { children: React.ReactNode }) {
return (
<div id="page-container">
<div
id="page-content"
style={{
padding: 20,
paddingBottom: 50,
minHeight: '100vh',
}}
>
{children}
</div>
</div>
)
}

function Logo() {
return (
<div
style={{
marginTop: 20,
marginBottom: 10,
}}
>
<a href="/">
<img src={logoUrl} height={64} width={64} />
</a>
</div>
)
}
29 changes: 29 additions & 0 deletions examples/redux/layouts/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* Links */
a {
text-decoration: none;
}
#sidebar a {
padding: 2px 10px;
margin-left: -10px;
}
#sidebar a.is-active {
background-color: #eee;
}

/* Reset */
body {
margin: 0;
font-family: sans-serif;
}
* {
box-sizing: border-box;
}

/* Page Transition Anmiation */
#page-content {
opacity: 1;
transition: opacity 0.3s ease-in-out;
}
body.page-is-transitioning #page-content {
opacity: 0;
}
38 changes: 38 additions & 0 deletions examples/redux/lib/features/counter/counterSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createSlice } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'

export interface CounterSliceState {
value: number
}

const initialState: CounterSliceState = {
value: 0,
}

export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload
},
initializeCount: (state, action: PayloadAction<number>) => {
state.value = action.payload
},
},
selectors: {
selectCount: (counter) => counter.value,
},
})

export const { selectCount } = counterSlice.selectors

export const { increment, decrement, incrementByAmount, initializeCount } = counterSlice.actions

export default counterSlice.reducer
8 changes: 8 additions & 0 deletions examples/redux/lib/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This file serves as a central hub for re-exporting pre-typed Redux hooks.
import { useDispatch, useSelector, useStore } from 'react-redux'
import type { AppDispatch, AppStore, RootState } from '../pages/+redux'

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
export const useAppStore = useStore.withTypes<AppStore>()
22 changes: 22 additions & 0 deletions examples/redux/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite build && vite preview"
},
"dependencies": {
"@reduxjs/toolkit": "^2.5.0",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
"@vitejs/plugin-react": "^4.2.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-redux": "^9.2.0",
"typescript": "^5.3.3",
"vike": "^0.4.211",
"vike-react": "^0.5.12",
"vike-react-redux": "^0.0.0",
"vite": "^5.4.0"
},
"type": "module"
}
15 changes: 15 additions & 0 deletions examples/redux/pages/+config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Config } from 'vike/types'
import Layout from '../layouts/LayoutDefault'
import Head from '../layouts/HeadDefault'
import vikeReact from 'vike-react/config'
import vikeReactRedux from 'vike-react-redux/config'

// Default configs (can be overridden by pages)
export default {
Layout,
Head,
// <title>
title: 'My Vike + React App',
extends: [vikeReact, vikeReactRedux],
passToClient: ['routeParams'],
} satisfies Config
22 changes: 22 additions & 0 deletions examples/redux/pages/+redux.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export { redux }

import { combineReducers, configureStore } from '@reduxjs/toolkit'
import counterReducer from '../lib/features/counter/counterSlice'

const rootReducer = combineReducers({ counter: counterReducer })

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

// Infer the type of 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']
12 changes: 12 additions & 0 deletions examples/redux/pages/about/+Page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react'
import { Counter } from '../../components/Counter'

export default function Page() {
return (
<>
<h1>About</h1>
<p>The counter value is the same as on the Welcome page.</p>
<Counter />
</>
)
}
17 changes: 17 additions & 0 deletions examples/redux/pages/index/+Page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react'
import { Counter } from '../../components/Counter'

export default function Page() {
return (
<>
<h1>My Vike app</h1>
This page is:
<ul>
<li>Rendered to HTML.</li>
<li>
Interactive. <Counter />
</li>
</ul>
</>
)
}
8 changes: 8 additions & 0 deletions examples/redux/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Example of using `vike-react-redux`.

```bash
git clone [email protected]:vikejs/vike-react
cd vike-react/examples/redux/
npm install
npm run dev
```
13 changes: 13 additions & 0 deletions examples/redux/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"strict": true,
"module": "ES2020",
"moduleResolution": "Node",
"target": "ES2020",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"types": ["vite/client"],
"jsx": "react",
"skipLibCheck": true,
"esModuleInterop": true
}
}
7 changes: 7 additions & 0 deletions examples/redux/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import react from '@vitejs/plugin-react'
import vike from 'vike/plugin'
import { UserConfig } from 'vite'

export default {
plugins: [react(), vike()],
} satisfies UserConfig
Loading

0 comments on commit 418fa29

Please sign in to comment.