redux-react-route v4/v5 push() 在 thunk 动作中不起作用
redux-react-route v4/v5 push() is not working inside thunk action
在 index.js
中直接推送或抛出调度效果很好:
...
import { push } from 'react-router-redux'
const browserHistory = createBrowserHistory()
export const store = createStore(
rootReducer,
applyMiddleware(thunkMiddleware, routerMiddleware(browserHistory))
)
// in v5 this line is deprecated
export const history = syncHistoryWithStore(browserHistory, store)
history.push('/any') // works well
store.dispatch(push('/any')) // works well
ReactDOM.render((
<Provider store={store}>
<Router history={history}>
<App />
</Router>
</Provider>
), document.getElementById('root'))
App.js
class App extends Component {
render() {
return (
<div className="app">
<Switch>
<Route path="/" component={Main} />
<Route path="/any" component={Any} />
</Switch>
</div>
);
}
}
export default withRouter(connect(/*...*/)(App))
但在 redux-thunk
操作中,所有尝试都以重写 url 结束,但 没有重新渲染
...
export function myAction(){
return (dispatch) => {
// fetch something and then I want to redirect...
history.push('/any') // change url but not re-render
dispatch(push('/any')) // change url but not re-render
store.dispatch(push('/any')) // change url but not re-render
}
}
这个 myAction
正在内部调用 fetch() 并且应该在成功后重定向。
如果我 运行 this.props.history.push('/any')
在组件内部,它就可以工作!但我需要 运行 在成功 fetch()
后重定向 inside thunk action
我试图用 withRouter
或 Route
包装所有组件,但没有帮助。
将 history
对象注入您的组件并像这样使用推送:
import { withRouter } from 'react-router-dom'
import { connect } from 'react-redux'
@withRouter
@connect(({auth})=>({auth}))
class App extends Component {
// on redux state change
componentWillReceiveProps(nextProps) {
if(!nextProps.auth)
this.props.history.push('/login')
}
render() {
return (
<div>
<Button
// on button click
onClick={this.props.history.push('/')}
>
Home page
</Button>
</div>
);
}
}
我通过将 successfull fetch() 的状态委托给 history.push()
或 <Redirect>
工作的组件(感谢@oklas)来解决问题:
{this.props.fetchSuccessfull && <Redirect to="/any" />}
但仍在等待更好的解决方案,直接从 thunk 操作调用 push()。
好吧,让我通过将调度中的历史对象传递给操作来提交另一个不完美的解决方案。我想它更像是一个初学者解决方案,但恕我直言,易于理解(因此易于维护,这是软件开发中最重要的事情)
使用 使所有 React 组件在其 props 中具有历史记录。很方便。但是,正如问题描述所述,您希望它在 React 组件之外,就像对 Redux-Thunk 的操作一样。
我没有回到 ,而是选择坚持使用 BrowserRouter。
- 无法在 React Components 外部访问 history 对象
- 我不喜欢回到
并使用像 react-router-redux 这样的东西
剩下的唯一选择是将历史对象传递给操作。
在 Auth-ForgotPassword 组件中:
const submitHandler = (data) => {
dispatch(authActions.forgotpassword({data, history:props.history}));
}
在动作函数中
export const forgotpassword = ({forgotpasswordData, history}) => {
return async dispatch => {
const url = settings.api.hostname + 'auth/forgotpassword'; // Go to the API
const responseData = await fetch(
url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify(forgotpasswordData),
}
);
history.push('/auth/forgotpassword/success');
}
}
现在我们都在等待最终的优雅解决方案:-)
在 index.js
中直接推送或抛出调度效果很好:
...
import { push } from 'react-router-redux'
const browserHistory = createBrowserHistory()
export const store = createStore(
rootReducer,
applyMiddleware(thunkMiddleware, routerMiddleware(browserHistory))
)
// in v5 this line is deprecated
export const history = syncHistoryWithStore(browserHistory, store)
history.push('/any') // works well
store.dispatch(push('/any')) // works well
ReactDOM.render((
<Provider store={store}>
<Router history={history}>
<App />
</Router>
</Provider>
), document.getElementById('root'))
App.js
class App extends Component {
render() {
return (
<div className="app">
<Switch>
<Route path="/" component={Main} />
<Route path="/any" component={Any} />
</Switch>
</div>
);
}
}
export default withRouter(connect(/*...*/)(App))
但在 redux-thunk
操作中,所有尝试都以重写 url 结束,但 没有重新渲染
...
export function myAction(){
return (dispatch) => {
// fetch something and then I want to redirect...
history.push('/any') // change url but not re-render
dispatch(push('/any')) // change url but not re-render
store.dispatch(push('/any')) // change url but not re-render
}
}
这个 myAction
正在内部调用 fetch() 并且应该在成功后重定向。
如果我 运行 this.props.history.push('/any')
在组件内部,它就可以工作!但我需要 运行 在成功 fetch()
我试图用 withRouter
或 Route
包装所有组件,但没有帮助。
将 history
对象注入您的组件并像这样使用推送:
import { withRouter } from 'react-router-dom'
import { connect } from 'react-redux'
@withRouter
@connect(({auth})=>({auth}))
class App extends Component {
// on redux state change
componentWillReceiveProps(nextProps) {
if(!nextProps.auth)
this.props.history.push('/login')
}
render() {
return (
<div>
<Button
// on button click
onClick={this.props.history.push('/')}
>
Home page
</Button>
</div>
);
}
}
我通过将 successfull fetch() 的状态委托给 history.push()
或 <Redirect>
工作的组件(感谢@oklas)来解决问题:
{this.props.fetchSuccessfull && <Redirect to="/any" />}
但仍在等待更好的解决方案,直接从 thunk 操作调用 push()。
好吧,让我通过将调度中的历史对象传递给操作来提交另一个不完美的解决方案。我想它更像是一个初学者解决方案,但恕我直言,易于理解(因此易于维护,这是软件开发中最重要的事情)
使用
我没有回到
- 无法在 React Components 外部访问 history 对象
- 我不喜欢回到
并使用像 react-router-redux 这样的东西
剩下的唯一选择是将历史对象传递给操作。
在 Auth-ForgotPassword 组件中:
const submitHandler = (data) => {
dispatch(authActions.forgotpassword({data, history:props.history}));
}
在动作函数中
export const forgotpassword = ({forgotpasswordData, history}) => {
return async dispatch => {
const url = settings.api.hostname + 'auth/forgotpassword'; // Go to the API
const responseData = await fetch(
url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify(forgotpasswordData),
}
);
history.push('/auth/forgotpassword/success');
}
}
现在我们都在等待最终的优雅解决方案:-)