Skip to content

Instantly share code, notes, and snippets.

@anthonyjoeseph
Last active October 24, 2020 14:46
Show Gist options
  • Save anthonyjoeseph/24b7114c7e81fc8c057a01d2114b274b to your computer and use it in GitHub Desktop.
Save anthonyjoeseph/24b7114c7e81fc8c057a01d2114b274b to your computer and use it in GitHub Desktop.
Attempt at redux-immutable integration with @morphic-ts/adt
import { makeADT, ADTType, ofType } from '@morphic-ts/adt'
import { combineReducers } from 'redux-immutable';
import { Action, createStore, Reducer } from 'redux';
import * as Immutable from 'immutable'
interface Ignition { type: 'Ignition' }
interface Accelerate { type: 'Accelerate' }
interface Brake { type: 'Brake' }
const AppAction = makeADT('type')({
Ignition: ofType<Ignition>(),
Accelerate: ofType<Accelerate>(),
Brake: ofType<Brake>(),
})
type AppAction = ADTType<typeof AppAction>
// type AppAction = Ignition | Accelerate | Brake
const initialState = Immutable.Record<{ vehicle: string, other: number }>({
vehicle: 'Idle',
other: 0
})
const morphicReducer: Reducer<string, AppAction> = AppAction.createReducer<string>('Idle')({
Ignition: (a: Ignition) => (s: string) => 'Starting Up',
Accelerate: (a: Accelerate) => (s: string) => 'Accelerating',
Brake: (a: Brake) => (s: string) => 'Braking',
})
const otherReducer: Reducer<number, AppAction> = (s?: number, a: AppAction): number => s ? s + 3 : 0
const rootReducer: Reducer<{ vehicle: string; other: number; }, Action> = combineReducers({
vehicle: morphicReducer,
other: otherReducer,
})
const store = createStore(rootReducer, initialState())
@erlandsona
Copy link

So I believe this will type check but immutable's implementation depends on every object in the graph being an Immutable one. See redux-immutable/src/combineReducers.js#L22
I'll paste the return of it here for brevity.

    return inputState
      .withMutations((temporaryState) => {
        reducerKeys.forEach((reducerName) => {
          const reducer = reducers[reducerName];
          const currentDomainState = temporaryState.get(reducerName);
          const nextDomainState = reducer(currentDomainState, action);

          validateNextState(nextDomainState, reducerName, action);

          temporaryState.set(reducerName, nextDomainState);
        });
      });

More specifically this is where I've run into trouble so far.

          const currentDomainState = temporaryState.get(reducerName);

And

          temporaryState.set(reducerName, nextDomainState);

Where the immutable version of combineReducers is dependent on having a get and set method on the object.

That said, currently I'm working through a version that only uses combineReducers to integrate with only the top level of our existing redux store.
🤞

@erlandsona
Copy link

So by some miracle I was able to integrate the Morphic generated reducer with Immutables combineReducer's and everything "Just Worked"! At least I was able to get dispatch ButtonClicked action to fire off a console.log in the reducer so woo!

@anthonyjoeseph
Copy link
Author

Ah yes it typechecks but I never actually ran it. I didn't know that about combineReducers. So glad it worked!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment