Skip to content

Commit

Permalink
Merge pull request #2025 from FaberVitale/fix/alm-update-counter-example
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson authored Feb 13, 2022
2 parents d1d9ef9 + 8e8676d commit 6e1d675
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 73 deletions.
2 changes: 1 addition & 1 deletion examples/action-listener/counter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.6.0-rc.1",
"@rtk-incubator/action-listener-middleware": "^0.6.0",
"@rtk-incubator/action-listener-middleware": "^0.8.0",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
Expand Down
36 changes: 36 additions & 0 deletions examples/action-listener/counter/src/components/App/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useEffect } from 'react'
import { Provider } from 'react-redux'
import type { Unsubscribe } from '@reduxjs/toolkit'
import { setupThemeListeners } from '../../services/theme/listeners'
import { setupCounterListeners } from '../../services/counter/listeners'
import { ChangeThemeForm } from '../ChangeThemeForm/ChangeThemeForm'
import { CounterList } from '../CounterList/CounterList'
import { CreateCounterForm } from '../CreateCounterForm/CreateCounterForm'
import { store, startAppListening } from '../../store'


export function App() {
useEffect(() => {
const subscriptions: Unsubscribe[] = [
setupCounterListeners(startAppListening),
setupThemeListeners(startAppListening),
]

return () => subscriptions.forEach((unsubscribe) => unsubscribe())
}, [])

return (
<React.StrictMode>
<Provider store={store}>
<main className={'main'}>
<header className="App-header">
<h1>Counter example</h1>
</header>
<ChangeThemeForm />
<CreateCounterForm />
<CounterList />
</main>
</Provider>
</React.StrictMode>
)
}
22 changes: 2 additions & 20 deletions examples/action-listener/counter/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import { Provider } from 'react-redux'
import { store } from './store'
import { themeActions } from './services/theme/slice'
import { ChangeThemeForm } from './components/ChangeThemeForm/ChangeThemeForm'
import { CounterList } from './components/CounterList/CounterList'
import { CreateCounterForm } from './components/CreateCounterForm/CreateCounterForm'
import { App } from './components/App/App'

if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
store.dispatch(themeActions.changeColorScheme('dark'))
}

ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<main className={'main'}>
<header className="App-header">
<h1>Counter example</h1>
</header>
<ChangeThemeForm />
<CreateCounterForm />
<CounterList />
</main>
</Provider>
</React.StrictMode>,
document.getElementById('root')
)
ReactDOM.render(<App />, document.getElementById('root'))
20 changes: 9 additions & 11 deletions examples/action-listener/counter/src/services/counter/listeners.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { counterActions, counterSelectors } from './slice'
import { AnyAction, isAllOf, isAnyOf, PayloadAction } from '@reduxjs/toolkit'
import type { AppListenerApi, AppActionListenerMiddleware } from '../../store'
import { AnyAction, isAllOf, isAnyOf, PayloadAction, Unsubscribe } from '@reduxjs/toolkit'
import type { AppListenerEffectAPI, AppStartListening } from '../../store'

function shouldStopAsyncTasksOf(id: string) {
return isAllOf(
Expand All @@ -14,7 +14,7 @@ async function onUpdateByPeriodically(
{
payload: { id, delta },
}: ReturnType<typeof counterActions.updateByPeriodically>,
{ dispatch, getState, getOriginalState, condition }: AppListenerApi
{ dispatch, getState, getOriginalState, condition }: AppListenerEffectAPI
) {
const counter = counterSelectors.selectById(getState(), id)

Expand Down Expand Up @@ -44,7 +44,7 @@ async function onUpdateAsync(
{
payload: { id, delta, delayMs },
}: ReturnType<typeof counterActions.updateByAsync>,
{ condition, dispatch, getState }: AppListenerApi
{ condition, dispatch, getState }: AppListenerEffectAPI
) {
const counter = counterSelectors.selectById(getState(), id)

Expand All @@ -70,17 +70,15 @@ async function onUpdateAsync(
* }, []);
* ```
*/
export function setupCounterListeners(
actionListener: AppActionListenerMiddleware
) {
export function setupCounterListeners(startListening: AppStartListening): Unsubscribe {
const subscriptions = [
actionListener.addListener({
startListening({
actionCreator: counterActions.updateByPeriodically,
listener: onUpdateByPeriodically,
effect: onUpdateByPeriodically,
}),
actionListener.addListener({
startListening({
actionCreator: counterActions.updateByAsync,
listener: onUpdateAsync,
effect: onUpdateAsync,
}),
]

Expand Down
25 changes: 13 additions & 12 deletions examples/action-listener/counter/src/services/theme/listeners.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { themeActions } from './slice'
import type { AppActionListenerMiddleware } from '../../store'
import type { AppStartListening } from '../../store'
import { Unsubscribe } from '@reduxjs/toolkit'

function onChangeColorScheme(
action: ReturnType<typeof themeActions.changeColorScheme>
) {
if (action.payload === 'light') {
document.documentElement.classList.remove('dark')
} else {
document.documentElement.classList.add('dark')
}
document.documentElement.classList.toggle('dark', action.payload !== 'light')
}

export function setupThemeListeners(
actionListener: AppActionListenerMiddleware
) {
return actionListener.addListener({
actionCreator: themeActions.changeColorScheme,
listener: onChangeColorScheme,
})
startListening: AppStartListening
): Unsubscribe {
const listeners = [
startListening({
actionCreator: themeActions.changeColorScheme,
effect: onChangeColorScheme,
}),
]

return () => listeners.forEach((unsubscribe) => unsubscribe())
}
32 changes: 14 additions & 18 deletions examples/action-listener/counter/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import { configureStore } from '@reduxjs/toolkit'
import { counterSlice } from './services/counter/slice'
import {
createActionListenerMiddleware,
ActionListenerMiddlewareAPI,
ActionListenerMiddleware,
createListenerMiddleware,
TypedStartListening,
TypedAddListener,
ListenerEffectAPI,
addListener,
} from '@rtk-incubator/action-listener-middleware'
import { themeSlice } from './services/theme/slice'
import { setupCounterListeners } from './services/counter/listeners'
import { setupThemeListeners } from './services/theme/listeners'

const actionListenerMiddleware = createActionListenerMiddleware({
const listenerMiddlewareInstance = createListenerMiddleware({
onError: () => console.error,
})

Expand All @@ -19,7 +19,7 @@ const store = configureStore({
[counterSlice.name]: counterSlice.reducer,
[themeSlice.name]: themeSlice.reducer,
},
middleware: (gDM) => gDM().prepend(actionListenerMiddleware),
middleware: (gDM) => gDM().prepend(listenerMiddlewareInstance.middleware),
})

export { store }
Expand All @@ -29,19 +29,15 @@ export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch

export type AppListenerApi = ActionListenerMiddlewareAPI<RootState, AppDispatch>
export type AppActionListenerMiddleware = ActionListenerMiddleware<
RootState,
AppDispatch
>
export type AppListenerEffectAPI = ListenerEffectAPI<RootState, AppDispatch>

// Typed version of `actionListenerMiddleware`
export const appActionListener =
actionListenerMiddleware as AppActionListenerMiddleware
export type AppStartListening = TypedStartListening<RootState>
export type AppAddListener = TypedAddListener<RootState>

export const startAppListening =
listenerMiddlewareInstance.startListening as AppStartListening
export const addAppListener = addListener as AppAddListener

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

setupCounterListeners(appActionListener)
setupThemeListeners(appActionListener)
13 changes: 2 additions & 11 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3673,7 +3673,7 @@ __metadata:
resolution: "@examples-action-listener/counter@workspace:examples/action-listener/counter"
dependencies:
"@reduxjs/toolkit": ^1.6.0-rc.1
"@rtk-incubator/action-listener-middleware": ^0.6.0
"@rtk-incubator/action-listener-middleware": ^0.8.0
"@types/node": ^12.0.0
"@types/react": ^17.0.0
"@types/react-dom": ^17.0.0
Expand Down Expand Up @@ -5513,16 +5513,7 @@ __metadata:
languageName: node
linkType: hard

"@rtk-incubator/action-listener-middleware@npm:^0.6.0":
version: 0.6.0
resolution: "@rtk-incubator/action-listener-middleware@npm:0.6.0"
peerDependencies:
"@reduxjs/toolkit": ^1.6.0
checksum: 01e600a9e513f883e4c6d02cbe4565b9691d6b43ebff432a9ad7f4f96d07c3164c3a0c14fde4391e3d3f65e18753e567b67d9645a2af27daba6b0aadd5fa2066
languageName: node
linkType: hard

"@rtk-incubator/action-listener-middleware@workspace:packages/action-listener-middleware":
"@rtk-incubator/action-listener-middleware@^0.8.0, @rtk-incubator/action-listener-middleware@workspace:packages/action-listener-middleware":
version: 0.0.0-use.local
resolution: "@rtk-incubator/action-listener-middleware@workspace:packages/action-listener-middleware"
dependencies:
Expand Down

0 comments on commit 6e1d675

Please sign in to comment.