andyrj / hyperapp-redux-devtools

hyperapp HOA to utilize redux-devtools-extension from hyperapp
MIT License
36 stars 5 forks source link

Non-nested actions are passed to the module's async action #12

Closed mickeyvip closed 6 years ago

mickeyvip commented 6 years ago

Hello.

I am toying with https://zaceno.github.io/hypercraft/post/modular-apps/ and when adding devtools, the module's async action gets the correct state but incorrect actions - top level actions.

I might be doing something wrong, but without wrapping the app with devtools the app works fine.

Here is the Chrome's DevTools. I highlighted the "Local" section where it can be seen that the actions are the wrong ones (top level) and the state is correct: image

And the exception: image

Here is the code:

CNJoke.js

import { h } from 'hyperapp';

export default initial => ({
    state: {
        joke: initial || '',
        fetching: false
    },
    actions: {
        fetchJoke: () => (state, actions) => {
            fetch('https://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]')
                .then(data => data.json())
                .then(jokeData => actions.setJoke(jokeData.value.joke));
            return { fetching: true };
        },
        setJoke: value => state => ({ joke: value, fetching: false })
    },
    view: (state, actions) => ({
        CNJoke: () => (
            <div>
                <button
                    onclick={() => actions.fetchJoke()}
                    disabled={state.fetching}
                >
                    {state.fetching ? 'Fetching Joke...' : 'Fetch Joke'}
                </button>
                <h2>{state.joke}</h2>
            </div>
        )
    })
});

App.js

import { h, app } from 'hyperapp';
import { Link, Route, Switch, location } from '@hyperapp/router';
import cnJoke from './CNJoke';

const cnJokeModule = cnJoke();

const state = {
    location: location.state,
    cnJoke: cnJokeModule.state
};

const actions = {
    location: location.actions,
    cnJoke: cnJokeModule.actions
};

const Home = props => <h2>Home</h2>;

const CNJoke = views => (
    <div>
        <h2>Chuck Norris Joke</h2>
        <views.CNJoke />
    </div>
);

const view = (state, actions) => {
    const views = {
        cnJoke: cnJokeModule.view(state.cnJoke, actions.cnJoke)
    };
    return (
        <div>
            <ul>
                <li>
                    <Link to="/">Home</Link>
                </li>
                <li>
                    <Link to="/cnjoke">Chun Norris Joke</Link>
                </li>
            </ul>

            <hr />

            <Switch>
                <Route path="/" render={Home} />
                 <Route path="/cnjoke" render={() => CNJoke(views.cnJoke)} />
            </Switch>
        </div>
    );
};

let main;
let unsubscribe;

if (process.env.NODE_ENV !== 'production') {
    import('hyperapp-redux-devtools').then(devtools => {
        main = devtools(app)(state, actions, view, document.body);
        unsubscribe = location.subscribe(main.location);
    });
} else {
    main = app(state, actions, view, document.body);
    unsubscribe = location.subscribe(main.location);
}
andyrj commented 6 years ago

Looking into this, you definitely aren't doing anything wrong, this is a bug. Thank you for the detailed bug report, I will fix this asap.

andyrj commented 6 years ago

Closing this issue published version 1.1.5 to npm which should correct this bug.

mickeyvip commented 6 years ago

That was blazingly fast! Thank you!

andyrj commented 6 years ago

just published 1.1.6 to fix the regression 1.1.5 introduced, I broke root actions getting the right actions object with that fix lol... just pulled get() from hyperapp source to correct this properly this time.

mickeyvip commented 6 years ago

@andyrj , should @hyperapp/router show the correct route view when traveling through states?

The view doesn't change...

UPDATE: looks like the view changes only when location changes... so it's how @hyperapp/router works. This is the problem with time traveling debugger and side effects.

andyrj commented 6 years ago

@mickeyvip when I was more active with hyperapp I had my own router that wired up location into the state and would update to correct views when time traveling. I'm not sure what changed with hyperapp/router it used to store the location in the state something like this... https://github.com/ajces/router/blob/master/src/router.js#L18

It's only a problem if you're router decides to not store the routing data in the state...