React-Router v4 + Redux-Saga навигация

Я пытаюсь переместить пользователя после успешного процесса аутентификации (после входа в систему / регистрации), однако, похоже, что любое решение, которое я нашел в Интернете - stackru / github проблемы / medium и т. Д. - не работает!

пожалуйста, найдите мой код ниже.

import { call, put, takeLatest } from 'redux-saga/effects'
import { push } from 'react-router-redux'

import { USER_LOGIN_SUCCEEDED, USER_LOGIN_FAILED, USER_LOGIN_REQUESTED } from '../actions/types'

import { login } from '../api'

function * loginUser (action) {
  try {
    const token = yield call(login, action.payload.email, action.payload.password)
    yield put({type: USER_LOGIN_SUCCEEDED, token: token})
    yield put(push('/dashboard'))
  } catch (error) {
    yield put({type: USER_LOGIN_FAILED, error: error.message})
  }
}

function * loginSaga () {
  yield takeLatest(USER_LOGIN_REQUESTED, loginUser)
}

export default loginSaga

не уверен, если это необходимо, но я также вставлю свой код маршрутизатора

    import React from 'react'
import { Route } from 'react-router-dom'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'

import ForgotPasswordForm from './components/home-page/ForgotPasswordForm'
import LoginForm from './components/home-page/LoginForm'
import RegisterForm from './components/home-page/RegisterForm'
import ResetPasswordForm from './components/home-page/ResetPasswordForm'

import Dashboard from './containers/Dashboard'
import HomePage from './containers/HomePage'

import PrivateRoute from './helpers/privateRoute'

import './index.scss'

class App extends React.Component {
  componentDidMount () {
    const token = window.localStorage.token
    if (token) {
      this.props.dispatch({type: 'USER_LOGIN_SUCCEEDED', token: token})
    }
  }

  render () {
    return (
        <div>
          <Route exact path='/' component={HomePage} />
          <Route path='/login' component={LoginForm} />
          <Route path='/register' component={RegisterForm} />
          <Route path='/forgot-password' component={ForgotPasswordForm} />
          <Route path='/reset-password/:resetPasswordToken' component={ResetPasswordForm} />
          <PrivateRoute path='/dashboard' component={Dashboard} />
        </div>
    )
  }
}

App.propTypes = {
  dispatch: PropTypes.func.isRequired
}

export default connect()(App)

и, наконец, код index.js

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore, applyMiddleware, compose } from 'redux'
import createSagaMiddleware from 'redux-saga'
import { ConnectedRouter, routerMiddleware } from 'react-router-redux'
import createHistory from 'history/createBrowserHistory'

import App from './App.js'

import rootReducer from './reducers/rootReducer'
import setAuthorizationToken from './helpers/setAuthorizationToken'
import loginSaga from './sagas/loginSaga'
import registerSaga from './sagas/registerSaga'

const sagaMiddleware = createSagaMiddleware()

const history = createHistory()

const reduxRouterMiddleware = routerMiddleware(history)

const store = createStore(
  rootReducer,
  compose(
    applyMiddleware(sagaMiddleware, reduxRouterMiddleware),
    window.devToolsExtension ? window.devToolsExtension() : f => f
  )
)

sagaMiddleware.run(registerSaga)
sagaMiddleware.run(loginSaga)

if (window.localStorage.token) {
  setAuthorizationToken(window.localStorage.token)
}

render(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App />
    </ConnectedRouter>
  </Provider>,
  document.getElementById('app')
)

Есть идеи, почему это не работает? Я также пытался импортировать browserHistory в файл саги и использовать что-то вроде yield browserHistory.push('/dashboard')

Любая помощь будет высоко оценена.

небольшое обновление - я получаю эту ошибку сейчас

3 ответа

Решение

У вас полностью не настроен реагирующий маршрутизатор-редукс ( https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux)

Тебе нужно

  • ConnectedRouter
  • Маршрутизатор-редуктор
  • Промежуточное ПО маршрутизатора

В противном случае, приставка не знает, что делать с действием push - ни один редуктор или промежуточное ПО не знает об этом действии, поэтому они игнорируют его.

Вы можете использовать createHistory из пакета истории. передавая его реагирующему маршрутизатору и получая к нему доступ в саге.

/** history.js ****/
import {createBrowserHistory} from 'history'

export default createBrowserHistory({your_config_here})

/** saga.js ***/
import {... call} from 'redux-saga/effects'
import history from './history'
export default function* your_root_saga(){
  ...access history here or in your sub sagas...
  yield call([history, history.push], 'your_object_path')
}


/** index.js ****/
import history from './history'
import {Router, ...} from 'react-router-dom'
import your_root_saga from './sagas'
import {createSagaMiddleware} from 'redux-saga'

const sagaMiddleware = createSagaMiddleware()
...config_your_store_here...
sagaMiddleware.run(your_root_saga)


render( <Router history = {history}> ... </Router>
, document.getElementById('elementId'))

Похоже, вы забыли добавить routerReducer - Попробуйте это:

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore, applyMiddleware, compose,
  combineReducers  // need this to add the routerReducer
} from 'redux'
import createSagaMiddleware from 'redux-saga'
import {
  ConnectedRouter,
  routerMiddleware,
  routerReducer // you need the router reducer
} from 'react-router-redux'
import createHistory from 'history/createBrowserHistory'

import App from './App.js'

import rootReducer from './reducers/rootReducer'
import setAuthorizationToken from './helpers/setAuthorizationToken'
import loginSaga from './sagas/loginSaga'
import registerSaga from './sagas/registerSaga'

const sagaMiddleware = createSagaMiddleware()

const history = createHistory()

const reduxRouterMiddleware = routerMiddleware(history)

const store = createStore(
  combineReducers({...rootReducer, router: routerReducer}),
  compose(
    applyMiddleware(sagaMiddleware, reduxRouterMiddleware),
    window.devToolsExtension ? window.devToolsExtension() : f => f
  )
)

sagaMiddleware.run(registerSaga)
sagaMiddleware.run(loginSaga)

if (window.localStorage.token) {
  setAuthorizationToken(window.localStorage.token)  
}

render(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App />
    </ConnectedRouter>
  </Provider>,
  document.getElementById('app')
)
Другие вопросы по тегам