React-Router v4 + Redux-Saga 导航
React-Router v4 + Redux-Saga navigation
我试图在身份验证过程成功后(登录/注册后)移动用户,但看起来我在互联网上找到的所有解决方案都一样——Whosebug/github 问题/媒体等——都不起作用!
请在下面找到我的代码。
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')
)
知道为什么它不起作用吗?我还尝试在 saga 文件中导入 browserHistory 并使用 yield browserHistory.push('/dashboard')
之类的东西
我们将不胜感激。
小更新 - 我现在收到这个错误
您没有完全设置 react-router-redux (https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux)
你需要
- 已连接路由器
- 路由器减速器
- 路由器中间件
否则 redux 不知道如何处理推送操作 - 没有 reducer 或中间件知道该操作,因此它们会忽略它。
您似乎忘记添加 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')
)
您可以使用 history 包中的 createHistory。将其传递给 react-router 并在 sagas 中访问它。
/** 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'))
我试图在身份验证过程成功后(登录/注册后)移动用户,但看起来我在互联网上找到的所有解决方案都一样——Whosebug/github 问题/媒体等——都不起作用!
请在下面找到我的代码。
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')
)
知道为什么它不起作用吗?我还尝试在 saga 文件中导入 browserHistory 并使用 yield browserHistory.push('/dashboard')
我们将不胜感激。
小更新 - 我现在收到这个错误
您没有完全设置 react-router-redux (https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux)
你需要
- 已连接路由器
- 路由器减速器
- 路由器中间件
否则 redux 不知道如何处理推送操作 - 没有 reducer 或中间件知道该操作,因此它们会忽略它。
您似乎忘记添加 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')
)
您可以使用 history 包中的 createHistory。将其传递给 react-router 并在 sagas 中访问它。
/** 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'))