cyclejs-community / cyclic-router

Router Driver built for Cycle.js
MIT License
109 stars 25 forks source link

HTTP request send twice if route changed back #196

Open AndrejSperling opened 7 years ago

AndrejSperling commented 7 years ago

I have a strange behavior maybe someone can help. Currently I have a router component, that is loading all pages. On the StartPage I have a form that can POST some entries.

Now, if I made an POST request and switched from '/start' to '/feed' and back to '/start' the POST request is send a second time.


const routedComponent = (sources) => ({path, value}) => value({...sources, router: sources.router.path(path)});

const routes = {
    '/start': StartPage,
    '/feed': UnderConstructionPage,
    '*': NotFoundPage,
};

export function Router(sources: AppSources): AppSinks {
 const routes$: Stream<SwitchPathReturn> = sources.router.define(routes);
    const page$ = routes$.map(routedComponent(sources));

    const redirectStartpage$ = sources.router.history$
        .filter(loc => loc.pathname === '/')
        .mapTo('/start');

    return {
        DOM: page$.map(c => c.DOM || xs.empty()).flatten(),
        HTTP: page$.map(c => c.HTTP || xs.empty()).flatten(),
        router: xs.merge(page$.map(c => c.router || xs.empty()).flatten(), redirectStartpage$),
        onion: page$.map(c => c.onion || xs.empty()).flatten(),
    };
}

On the StartPage I have a intent that is listen to a HTTP stream. And if the response is successfull I show a message.

export function intent(sources: AppSources) {

    const {DOM,HTTP} = sources;

    return {
        newSetClick$: DOM.select(ID_NEW_SET_BTN).events('click').debug('CLICK'),
        refreshSetList$: xs.of(GetSetsApi.buildRequest()),
        newSetResponse$: HTTP.select(PostSetApi.ID).flatten()
    };

}

function reducer(action: any) {

    const initReducer$ = xs.of(function initReducer(state) {
        return {
            showNewCardMessage: false,
            newCardMessage: {}
        }
    });

    const newCardMessageReducer$ = action.newSetResponse$
        .filter(response => response.ok)
        .map(res => ({
            id: res.body._id,
            title: res.body.title
        }))
        .map(res => function cardMessageReducer(state) {
            return {
                ...state,
                showNewCardMessage: true,
                newCardMessage: {
                    id: res.id,
                    title: res.title
                }
            }
        });

    return xs.merge(initReducer$, newCardMessageReducer$);
}

The request is send by Startpage itself but only if the submit button was clicked. Now if I remove the "Intent" the behavior disapears.

ntilwalli commented 7 years ago

Is it this issue? https://github.com/cyclejs/cyclejs/issues/592

ntilwalli commented 7 years ago

Just FYI, if you'd like to test if that issue is what's causing the problem you can look at the changes I made in @cycle/run and @cycle/rxjs-run to hack a fix for it. The change can be reviewed here: https://github.com/ntilwalli/cyclejs/blob/stumplog/run/src/index.ts#L83

If you are using RxJS you can even use my forked (workaround) version or rxjs-run on npm called stump-rxjs-run and see if that fixes your issue.

AndrejSperling commented 7 years ago

@ntilwalli It sounds like the same issue, I tried your hack and it worked, but I have to test my app more to be sure that there are no other side effects.

But thanks for your help!