如何在安装React组件之前制作Saga观看事件?

时间:2016-11-11 16:55:33

标签: javascript reactjs react-router redux-saga

如果我将浏览器网址设置为:/uni-classi-virtuali/gestisci/1

componentWillMount开始之前调用组件DettaglioClasseVirtuale的函数rootSaga(我有获取资源调用的地方)。

是否有一种标准的方法可以让saga在应用程序启动时获取资源?

这是我的传奇观察者,用于获取资源“classivirtualiuni”项目:

export function* watchGetClasseVirtualiUni() {
    yield takeEvery(GET_CLASSE.REQUEST, getClasseVirtualiUni)
}

export function* getClasseVirtualiUni(action) {
    try {
        const data = yield call(fetchResource, `classivirtualiuni/${action.id}`)
        if (data.success) {
            yield put(getClasse.success(data.content))
        } else {
            yield put(getClasse.failure(data.message))
        }
    } catch (error) {
        yield put(getClasse.failure(error.message))
    }
}

由一个简单的希腊语召唤:

export default function* rootSaga() {
    yield [
        // ...
        // ...
        watchGetClasseVirtualiUni()
    ]
}

这是我的App类,由react-router处理:

class App extends Component {

    render() {
        return (
            <Router history={browserHistory}>
                <Route path={'/uni-classi-virtuali'} component={Main} >
                    <IndexRedirect to={'/uni-classi-virtuali/gestisci'} />
                    <Route path={'crea'} component={CreateClasseVirtualeUni} />
                    <Route path={'gestisci'} component={ClasseVirtualeList} >
                        <Route path={':id'} component={DettaglioClasseVirtuale} />
                    </Route>
                    <Route path={'iscriviti'} component={IscrivitiClasseVirtuale} />
                </Route>
            </Router>
        )
    }
}

这是调用获取数据的组件:

class DettaglioClasseVirtuale extends Component {

    componentWillMount() {
        // dispatch the GET_CLASSE.REQUEST action
        this.fetchClasseVirtuale(this.props.classeId) 
    }

    // ...
}

这是该应用程序的核心:

function configureStore(initialState) {
    const sagaMiddleware = createSagaMiddleware()
    let finalCreateStore = applyMiddleware(thunk, sagaMiddleware)(createStore)
    const store = finalCreateStore(reducer, initialState);
    store.runSaga = sagaMiddleware.run
    store.close = () => store.dispatch(END)
    return store;
}

const store = configureStore()
store.runSaga(rootSaga)

ReactDOM.render(
    <div>
        <Provider store={store}>
            <App />
        </Provider>
    </div>,
  document.getElementById('virtual-class')
)

3 个答案:

答案 0 :(得分:1)

我找到了一个干净简单的解决方法:在rootSaga中放置一个准备好的操作并在Main组件中等待它。

export default function* rootSaga() {
    yield [
        // ...
        // ...
        watchGetClasseVirtualiUni(),
        put(ready())
    ]
}
class App extends Component {

    render() {
        return (
            <Loader isLoaded={this.props.ready}>
                <Router history={browserHistory}>
                    <Route path={'/uni-classi-virtuali'} component={Main} >
                    {//...}
                    </Route>
                </Router>
            </Loader>
        )
    }
}

答案 1 :(得分:0)

您可以将getClasseVirtualiUni添加到在应用启动时运行的rootSaga,而不是通过watchGetClasseVirtualiUni收听操作。剩下的唯一问题是弄清楚如何传递通过组件传递的classeId

答案 2 :(得分:0)

使用反应样板时,我遇到了类似的问题。我使用compose()进行了修复。

不要这样做:

import { useInjectSaga } from 'utils/injectSaga';

export function App() {
  useInjectSaga({ key: 'app', saga }); //it's already too late, we're already loading the component

  return <div />;
}

export default compose()(App);

执行此操作:

import injectSaga from 'utils/injectSaga';

const key = 'app';

export function App() {
  return <div />;
}

const withSaga = injectSaga({ key, saga }); //this comes into play before the component loads

export default compose(withSaga)(App);

Source