我正在使用react-router v4和redux- saga。我正在尝试在页面加载时进行API调用。当我访问时/detailpage/slug/,我的应用程序似乎陷入了循环并无休止地调用了我的API端点。这是我的应用程序的设置方法。假设我的进口是正确的。
/detailpage/slug/
index.js
const history = createHistory() const sagaMiddleware = createSagaMiddleware() const middleware = [routerMiddleware(history), sagaMiddleware] const store = createStore( combineReducers({ aReducer }), applyMiddleware(...middleware) ) injectTapEventPlugin(); sagaMiddleware.run(rootSaga) ReactDOM.render( <Provider store={store}> <ConnectedRouter history={history}> <Switch> <Route path="/" exact component={HomePage} /> <Route path="/detailpage/:slug" component={Detail} /> <Route path="/page" component={Page} /> </Switch> </ConnectedRouter> </Provider>, document.getElementById('root') );
reducers / index.js
const aReducer = (state={}, action) => { switch(action.type) { case 'SHOW_DETAIL': console.log('Reducers: reducer called') return Object.assign({}, state, { name: 'adfsdf' }) default: return state; } } export default aReducer;
动作/ index.js
export const showDetailInfo = () => { console.log('action called') return { type: 'SHOW_DETAIL' } }
saga.js
export function* fetchDetailsAsync() { try { console.log('fetching detail info') const response = yield call(fetch, 'http://localhost:8000/object/1/', { method: 'GET', headers: { 'Authorization': 'Token xxxxxxxxxxxx' }}) console.log(response); yield put({type: 'SHOW_DETAIL', response: response.data}) } catch (e) { console.log('error') } } // watcher saga export function* fetchDetails() { console.log('watcher saga') yield takeEvery('SHOW_DETAIL', fetchDetailsAsync) } export default function* rootSaga() { console.log('root saga') yield [ fetchDetails() ] }
容器/Detail.js
const mapStateToProps = (state) => { return { name: 'Test' } } const mapDispatchToProps = (dispatch, ownProps) => { console.log('mapDispatchToProps') return { showDetailInfo: (payload) => { console.log('dispatching'); dispatch({ type: 'SHOW_DETAIL' }) } } } const Detail = connect( mapStateToProps, mapDispatchToProps )(DetailPage) export default Detail;
组件/DetailPage.js
class DetailPage extends React.Component { componentWillMount() { this.props.showDetailInfo(); } render() { return ( <Layout> <h3>DetailPage</h3> <p>{ this.props.name }</p> </Layout> ) } } DetailPage.PropTypes = { showDetailInfo: PropTypes.func.isRequired, name: PropTypes.string.isRequired } export default DetailPage;
我花了几天的时间进行故障排除,尝试各种想法,包括测试不同的生命周期方法,从applyMiddleware中删除routerMiddleware。
我以为我的组件在每个API调用之后都会更新,但是任何生命周期方法中的console.log都没有更新。
作为对生态系统做出反应的新手,这里有很多活动部件,这对我来说很难进行故障排除。
当然,您可以在接下来的几行中明确设置无限循环:
yield put({type: 'SHOW_DETAIL', response: response.data}) // ... yield takeEvery('SHOW_DETAIL', fetchDetailsAsync)
传奇并没有为您做任何神奇的事情,而只是订阅的初步层,并在动作和执行协程上生成。
解:
对于从React组件捕获的动作,以及用于对状态进行优化和实际更新的动作,应使用不同的名称。
yield takeEvery('SHOW_DETAIL_REQUEST', fetchDetailsAsync)以这种方式使用并命名您的动作。
yield takeEvery('SHOW_DETAIL_REQUEST', fetchDetailsAsync)
yield put({type: 'SHOW_DETAIL_SUCCESS', response: response.data})成功使用响应并以这种方式命名您的减速器
yield put({type: 'SHOW_DETAIL_SUCCESS', response: response.data})
除此之外,您还可以'SHOW_DETAIL_FAILURE'用于失败的传奇请求。
'SHOW_DETAIL_FAILURE'
上面所有名称均为常用大小写。