带有redux-saga的无限循环 [英] Infinite loop with redux-saga
问题描述
我正在使用react-router v4和redux-saga。我正在尝试在页面加载时进行API调用。当我访问 / detailpage / slug /
时,我的应用程序似乎陷入循环并无休止地调用我的API端点。这是我的应用程序的设置方式。假设我的导入是正确的。
I'm using react-router v4 and redux-saga. I'm attempting to make an API call when a page loads. When I visit /detailpage/slug/
, my application seems to get stuck in a loop and makes endless calls to my API endpoint. Here's how my application is setup. Assume my imports are correct.
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;
actions / 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()
]
}
containers / 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;
components / 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;
我花了几天时间进行故障排除,尝试各种想法,包括测试不同的生命周期方法,删除routerMiddleware来自applyMiddleware。
I've spent a few days troubleshooting, trying various ideas including testing different lifecycle methods, removing the routerMiddleware from applyMiddleware.
我认为我的组件在每次API调用后都在更新,但是来自任何生命周期方法的console.log表明它不是。
I thought that my component was updating after every API call, but console.log from any of the lifecycle methods indicates that it's not.
作为生态系统的新手,这里有很多活动部件,对我来说排除故障具有挑战性。
Being new to react ecosystem, there are a lot of moving parts here and it's challenging for me to troubleshoot.
推荐答案
当然,你明确地设置下一行的无限循环:
Of course, you explicitly set the infinite loop the next lines:
yield put({type: 'SHOW_DETAIL', response: response.data})
// ...
yield takeEvery('SHOW_DETAIL', fetchDetailsAsync)
这个传奇不会为你做任何神奇的事情,只是一个初步的一层动作和执行协同程序的订阅和生成。
The saga doesn't do any magic things for you, and only is a preliminary layer of a subscription and generation on actions and executions coroutines.
解决方案:
您应使用不同的名称进行操作从React组件中捕获,以及用于状态的乐观和实际更新的操作。
You shall use different names for actions which you catch from React components, and actions which are used for optimistical and real up-dating of a status.
使用 yield takeEvery('SHOW_DETAIL_REQUEST', fetchDetailsAsync)
并以这种方式命名您的操作。
Use yield takeEvery('SHOW_DETAIL_REQUEST', fetchDetailsAsync)
and name your action in this manner.
使用 yield put({type:'SHOW_DETAIL_SUCCESS',响应:response.data})
成功回复并以这种方式命名你的减速机
Use yield put({type: 'SHOW_DETAIL_SUCCESS', response: response.data})
in success response and name your reducer in this manner
不止于此,你c使用'SHOW_DETAIL_FAILURE'
用于失败的传奇请求。
More than that, you can use 'SHOW_DETAIL_FAILURE'
for failed saga request.
以上所有名称都是常见用例。
All names above are common-used case.
这篇关于带有redux-saga的无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!