Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sagas not getting unmounted #69

Closed
vasyl-purchel opened this issue Jan 13, 2017 · 2 comments
Closed

Sagas not getting unmounted #69

vasyl-purchel opened this issue Jan 13, 2017 · 2 comments

Comments

@vasyl-purchel
Copy link

Hi, I found a problem while trying to use react-router with redux-elm.

If I have simple components without sagas all works as in this example.

Through if I'm creating components with sagas as mentioned in tutorial I get a problem when changing location more then once to component with saga:

WARNING: The Saga instance has already been mounted, this basically mean that your Updaters do not form a tree, please be sure that every Updater is wrapped by another Updater (except root updater). It does not make sense to use combineReducers for Updaters.
log @ logger.js:8
warn @ logger.js:14
mount @ SagaRepository.js:49
(anonymous) @ Updater.js:132
(anonymous) @ storeEnhancer.js:54

I've used components from tutorial:

router/view.js:

import React from 'react';
import { connect } from 'react-redux';
import { forwardTo, view } from 'redux-elm';
import { Router, Route } from 'react-router';

import AppLayout from '../AppLayout';
import GifViewerPair from '../gif-viewer-pair/view';
import HelloWorld from '../HelloWorld/view';

const connectView = (View, modelKey, ...nesting) =>
  connect(appState => ({ model: appState.root[modelKey] }))(
    props => <View {...props} dispatch={forwardTo(props.dispatch, ...nesting)} />,
  );

const AppLayoutView = connectView(view(AppLayout), 'appLayout', 'AppLayout');
const GifViewerPairView = connectView(GifViewerPair, 'gifViewerPair', 'GifViewerPair');
const MonitorView = connectView(HelloWorld, 'helloWorld', 'HelloWorld');

export default view(({ history }) => (
  <Router history={history}>
    <Route path="/" component={AppLayoutView}>
      <Route path="gifViewer" component={GifViewerPairView} />
      <Route path="helloWorld" component={HelloWorldView} />
    </Route>
  </Router>
));

router/updater.js:

import { Updater } from 'redux-elm';
import gifViewerPairUpdater, { init as gifViewerPairInit } from '../gif-viewer-pair/updater';
import helloWorldUpdater, { init as helloWorldInit } from '../hello-world/updater';

export const initialModel = {
  gifViewerPair: gifViewerPairInit(),
  helloWorld: helloWorldInit(),
};

export default new Updater(initialModel)
  .case('GifViewerPair', (model, action) => (
    { ...model, gifViewerPair: gifViewerPairUpdater(model.gifViewerPair, action) }
  ))
  .case('HelloWorld', (model, action) => (
    { ...model, helloWorld: helloWorldUpdater(model.helloWorld, action) }
  ))
  .toReducer();

gif-viewer-pair/updater.js:

import { Updater, wrapAction } from 'redux-elm';
import { takeEvery } from 'redux-saga';
import { put } from 'redux-saga/effects';

import gifViewerUpdater, { init as gifViewerInit, requestMore } from '../gif-viewer/updater';

const initialModel = {
  top: gifViewerInit('ducks'),
  bottom: gifViewerInit('dinosaur'),
};

function* fetchAll() {
  yield put(wrapAction(requestMore(), 'Top'));
  yield put(wrapAction(requestMore(), 'Bottom'));
}

function* saga() {
  yield* takeEvery('Load', fetchAll);
}

export const init = () => initialModel;

export default new Updater(initialModel, saga)
  .case('Top', (model, action) =>
    ({ ...model, top: gifViewerUpdater(model.top, action) }))
  .case('Bottom', (model, action) =>
    ({ ...model, bottom: gifViewerUpdater(model.bottom, action) }))
  .toReducer();

gif-viewer-pair/view.js:

import React from 'react';
import { forwardTo, view } from 'redux-elm';

import GifViewer from '../gif-viewer/view';

export default view(({ model, dispatch }) => (
  <div>
    <GifViewer model={model.top} dispatch={forwardTo(dispatch, 'Top')} />
    <GifViewer model={model.bottom} dispatch={forwardTo(dispatch, 'Bottom')} />
    <br />
    <button onClick={() => dispatch({ type: 'Load' })}>Load Both!</button>
  </div>
));

So from some little investigation I found that when saga is created it is using action.matching.id (in my case it was GifViewerPair.) and adds saga into this.sagas["GifViewerPair."] (with dot at the end), while unmount saga looks by id GifViewerPair (with no dot at the end) and for sure it doesn't find it and not unmounting the saga.

So as the result when using react-router when component is Unmounted saga stay in the saga repository, and when we mount same component again by navigating back to page with that component it try to mount saga again, but saga is already there as same id with dot at the end is used.

@namjul
Copy link

namjul commented Jan 13, 2017

Also mentioned in #54 (comment)

@tomkis
Copy link
Collaborator

tomkis commented Feb 23, 2017

Closing because of irrelevance. prism v4 does not deal with Sagas anymore.

@tomkis tomkis closed this as completed Feb 23, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants