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

时间:2017-07-10 20:10:53

标签: reactjs react-router redux-thunk react-router-redux

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操作中,所有尝试都以重写网址结束,但不重新呈现

...
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 action 内运行重定向

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

3 个答案:

答案 0 :(得分:2)

history对象注入您的组件并使用push这样:

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

答案 1 :(得分:0)

我通过将successl fetch()的状态委托给组件(感谢@oklas)来history.push()<Redirect>工作,从而制定了解决方法:

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

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

答案 2 :(得分:0)

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

使用可使所有React-compoment在其道具中都具有历史记录。很方便。但是,正如问题描述所述,您希望它在React组件之外,就像对Redux-Thunk的操作一样。

我选择继续使用BrowserRouter,而不是回到

  • 无法在React Components外部访问历史对象
  • 我不喜欢回到并使用类似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');
    }
}

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