2016-12-31 73 views
0

下面是我的登陸傳奇的一個片段:陣營傳奇生命週期

export function* loginFlow() { 
    while (true) { 
    const request = yield take(LOGIN_REQUEST); 
    const { username, password } = request.data; 

    const authResp = yield call(authorize, { username, password }); 
    if (authResp) { 
     yield put({ type: SET_AUTH, newAuthState: true }); // User is logged in (authorized) 
     yield put({ type: CHANGE_FORM, newFormState: { username: '', password: '' } }); // Clear form 
     forwardTo('/home'); // Go to dashboard page 
    } 
    } 
} 

這個傳奇是我LoginContainer。現在每次進入登錄屏幕並加載登錄容器時,都會產生一個新的傳奇「進程」,所以每次我重新訪問登錄屏幕時,當我點擊「登錄」時,越來越多的請求會進入我的登錄API,按鈕。

我能以某種方式銷燬組件銷燬時的傳奇故事嗎?

編輯:下面是一個嘗試取消傳奇:

export function* loginFlow() { 
    const request = yield take(LOGIN_REQUEST); 
    const { username, password } = request.data; 

    const authResp = yield call(authorize, { username, password }); 
    if (authResp) { 
    yield put({ type: SET_AUTH, newAuthState: true }); // User is logged in (authorized) 
    yield put({ type: CHANGE_FORM, newFormState: { username: '', password: '' } }); // Clear form 
    forwardTo('/home'); // Go to dashboard page 
    } 
} 

export function* watchLogin() { 
    // or takeEvery (according to your business logic) 
    yield* takeEvery(LOGIN_REQUEST, loginFlow); 
} 

export function* root() { 
    const watchers = [ 
    yield fork(watchLogin), 
    ]; 

    // Cancel all watchers on location change 
    yield take(LOCATION_CHANGE); 

    watchers.forEach(function(watcher) { 
    console.log("cancelling watcher") 
    cancel(watcher) 
    }); 
} 

// All sagas to be loaded 
export default [ 
    root, 
]; 

我必須登錄按鈕點擊兩次初始負載,從而使API請求是人工做的,然後我遇到了與以前相同的行爲 - 傳奇不會被取消,並且請求不斷加起來。

這裏是我的組件:

export class Login extends React.Component { 
    constructor(props) { 
    super(props); 
    this.login = this.login.bind(this); 
    this.onChange = this.onChange.bind(this); 
    } 

    onChange(newFormState) { 
    this.props.dispatch(changeForm(newFormState)); 
    } 

    login(username, password) { 
    console.log("dispatching login request") 
    this.props.dispatch(loginRequest({ username, password })); 
    } 

    render() { 
    const { formState, currentlySending, error } = this.props; 

    return (
     <Wrapper> 
     <LoginForm onChange={this.onChange} data={formState} error={error} currentlySending={currentlySending} btnText={messages.btnText} usernameText={messages.usernameText} passwordText={messages.passwordText} onSubmit={this.login} /> 
     </Wrapper> 
    ); 
    } 
} 

下面是如何加載我的傳奇(routes.js):

export default function createRoutes(store) { 
    // create reusable async injectors using getAsyncInjectors factory 
    const { injectReducer, injectSagas } = getAsyncInjectors(store); 

    return [ 
    { 
     path: '/login', 
     name: 'login', 
     getComponent(nextState, cb) { 
     const importModules = Promise.all([ 
      System.import('containers/Login/reducer'), 
      System.import('containers/Login/sagas'), 
      System.import('containers/Login'), 
     ]); 

     const renderRoute = loadModule(cb); 

     importModules.then(([reducer, sagas, component]) => { 
      injectReducer('login', reducer.default); 
      injectSagas(sagas.default); 
      renderRoute(component); 
     }); 

    importModules.catch(errorLoading); 
    }, 
... 

而這裏的,我認爲這是一個導致問題的forwardTo功能:

function forwardTo(location) { 
    browserHistory.push(location); 
} 

如果我在之前在傳奇的while循環中調用這個函數之前休息,那麼這個傳奇會被破壞自動和所有按預期工作。

回答

0

嗯,是的,你可以摧毀組件破壞你的傳奇觀察家,這將是要麼通過兩種方法:

  1. 添加爲組件操作裝載和卸載,然後在你的陣營組件方法,componentWillMount,調度安裝動作,並在componentWillUnmount調度卸載動作,並相應地處理你的傳說。

  2. 在第一次提到你會毀掉你的傳奇觀察家對頁/容器 NOT成分破壞,而你只是聽上LOCATION_CHANGE行動(也許從react-router-redux如果您使用它),而不是COMPONENT_UNMOUNT行動(上述方法


在這裏你去一個樣本應用秒方法在你的傳奇,也有一些修改爲您loginFlow傳奇發生器:

import {call, cancel, fork, put, take} from 'redux-saga/effects'; 
import {takeEvery, takeLatest} from 'redux-saga'; 
import {LOCATION_CHANGE} from 'react-router-redux'; 
import { 
    LOGIN_REQUEST, 
    SET_AUTH, 
    CHANGE_FORM, 
} from './constants'; 

export function* loginFlow() { 
    const request = yield take(LOGIN_REQUEST); 
    const { username, password } = request.data; 

    const authResp = yield call(authorize, { username, password }); 
    if (authResp) { 

    // User is logged in (authorized) 
    yield put({ type: SET_AUTH, newAuthState: true }); 

    // Clear form 
    yield put({ type: CHANGE_FORM, newFormState: { 
     username: '', 
     password: '' 
    } }); 

    forwardTo('/home'); // Go to dashboard page 
    } 
} 

export function* watchLogin() { 
    // or takeEvery (according to your business logic) 
    yield* takeLatest(LOGIN_REQUEST, loginFlow); 
} 

export function* root() { 
    const watchers = [ 
    yield fork(watchLogin), 
    ]; 

    // Cancel all watchers on location change 
    yield take(LOCATION_CHANGE); 
    watchers.forEach(cancel); 
} 

// All sagas to be loaded 
export default [ 
    root, 
]; 

現在如上圖所示,我們使用了一些redux-saga/effects傳奇觀察家對組件/容器的使用,然後使用取消摧毀的LOCATION_CHANGE觀察家。

此外,您需要派發您LOGIN_REQUEST按鈕在buttonComponent上的操作。


請澄清,如果有事不清楚。

redux-saga文檔here瞭解更多關於任務取消的信息。

+0

謝謝你,我已經編輯了原來的帖子,試圖實現上面的代碼,我仍然遇到怪異的行爲,並且這個傳奇並沒有被取消。 – Nirri

+0

我會問你在哪裏注入/加載你的傳奇?你還會寫下你的React組件來調查不正確的功能嗎? –

+0

我編輯了一些額外的數據原始帖子 – Nirri