redux-react-route v4/v5 push() 在 thunk 动作中不起作用

Posted

技术标签:

【中文标题】redux-react-route v4/v5 push() 在 thunk 动作中不起作用【英文标题】:redux-react-route v4/v5 push() is not working inside thunk action 【发布时间】:2017-12-14 16:52:05 【问题描述】:

index.js 中直接 push 或 throw dispatch 效果很好:

...
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()

在 thunk 操作中运行重定向

我试图用withRouterRoute 包装所有组件,但没有帮助。

【问题讨论】:

您使用哪个版本的react-router-redux?您需要使用与react-router v4 兼容的react-router-redux v5。 Th 包react-router-redux v5 目前正在积极开发中。 @oklas 现在我尝试在react-router-redux v5 上运行它,但它的行为与 v4 相同 这很可能还没有实现。作为解决方法,将此委托给 router history 对象可用的组件。您的推送事件始终出现在 thunk 队列的末尾,因此您可以使用重定向信息设置状态。 能否提供代码? Edited 通过提供更多代码进行查询,并且我还提供了一个答案,我如何解决此问题,但仍在等待是否有人提供解决方案如何直接从重击动作。 【参考方案1】:

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>
    );
  

【讨论】:

谢谢,看来没有更好的答案了。 谢谢,分享你的快乐。【参考方案2】:

我通过将成功 fetch() 的状态委托给 history.push()&lt;Redirect&gt; 工作的组件(感谢@oklas)来解决问题:

this.props.fetchSuccessfull && <Redirect to="/any" />

但仍然通过直接从 thunk 操作调用 push() 来等待更好的解决方案。

【讨论】:

【参考方案3】:

那么,让我通过将调度中的历史对象传递给操作来提交另一个不完美的解决方案。我想这更像是一个初学者的解决方案,但恕我直言,易于理解(因此易于维护,这是软件开发中最重要的事情)

使用 使所有 React 组件在其 props 中都有历史记录。很方便。但是,正如问题描述所述,您希望它在 React 组件之外,例如 Redux-Thunk 上的操作。

我选择坚持使用 BrowserRouter,而不是回到

历史对象无法在 React 组件之外访问 我不喜欢回到 并使用 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');
    

现在我们都在等待最终的优雅解决方案 :-)

【讨论】:

以上是关于redux-react-route v4/v5 push() 在 thunk 动作中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

UUID-五个版本-v1|v2|v3|v4|v5-使用说明

在数组的映射中不使用图形查找循环依赖

Pytorch深度学习50篇·······第五篇:YOLO----- YOLO V3 V4 V5的模型结构

计软考研双日练 | 深度优先遍历图的方法是什么?

vijos P1426兴奋剂检查 多维费用背包问题的hash

Kotlin 解构