带有redux-saga的无限循环

Chr*_*ris 5 javascript reactjs react-redux react-router-v4

我正在使用react-router v4和redux-saga.我正在尝试在页面加载时进行API调用.当我访问时/detailpage/slug/,我的应用程序似乎陷入循环并且无休止地调用我的API端点.这是我的应用程序的设置方式.假设我的导入是正确的.

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')
);
Run Code Online (Sandbox Code Playgroud)

减速器/ 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;
Run Code Online (Sandbox Code Playgroud)

动作/ index.js

export const showDetailInfo = () => {
  console.log('action called')
  return {
    type: 'SHOW_DETAIL'
  }
}
Run Code Online (Sandbox Code Playgroud)

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()
  ]
}
Run Code Online (Sandbox Code Playgroud)

集装箱/ 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;
Run Code Online (Sandbox Code Playgroud)

组件/ 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;
Run Code Online (Sandbox Code Playgroud)

我花了几天时间进行故障排除,尝试各种想法,包括测试不同的生命周期方法,从applyMiddleware中删除routerMiddleware.

我认为我的组件在每次API调用后都在更新,但是来自任何生命周期方法的console.log表明它不是.

作为生态系统的新手,这里有很多活动部件,对我来说排除故障具有挑战性.

Vla*_*ost 12

当然,您明确地将无限循环设置为下一行:

yield put({type: 'SHOW_DETAIL', response: response.data})
// ...
yield takeEvery('SHOW_DETAIL', fetchDetailsAsync)
Run Code Online (Sandbox Code Playgroud)

这个传奇并没有为你做任何神奇的事情,只是在动作和执行协同程序上进行订阅和生成的初步层.

解:

对于从React组件捕获的操作,以及用于状态的乐观和实际更新的操作,您应使用不同的名称.

yield takeEvery('SHOW_DETAIL_REQUEST', fetchDetailsAsync)以这种方式使用和命名您的操作.

用于yield put({type: 'SHOW_DETAIL_SUCCESS', response: response.data})成功响应并以此方式命名您的减速机

更重要的是,您可以使用'SHOW_DETAIL_FAILURE'失败的传奇请求.

以上所有名称都是常见的用例.

  • 谢谢!我是Redux的新手,并意识到它的强大功能。我仍在为事物的运作方式开发思维模型。这有助于澄清一些事情。 (2认同)