React history.push()不呈现新组件

zil*_*nas 4 javascript reactjs react-router-v4

大家好!

我有一个带有简单登录功能的React.js项目。在授权用户之后,我调用history.push方法,该方法会更改地址栏中的链接,但不会呈现新组件。(我使用BrowserRouter)

我的index.js组件:

ReactDOM.render(
  <Provider store={createStore(mainReducer, applyMiddleware(thunk))}>
    <BrowserRouter>
      <Main />
    </BrowserRouter>
  </Provider>,
  document.getElementById('root')
);
Run Code Online (Sandbox Code Playgroud)

我的Main.js组件:

const Main = (props) => {
  return (
    <Switch>
      <Route exact path="/" component={Signin} />
      <Route exact path="/servers" component={Servers} />
    </Switch>
)}

export default withRouter(Main);
Run Code Online (Sandbox Code Playgroud)

我的动作创作者

export const authorization = (username, password) => (dispatch) =>
  new Promise ((resolve, reject) => {
    fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        username: username,
        password: password,
      })
    }).then( response => {
      if (response.ok) {
          response.json().then( result => {
            console.log("API reached.");
            dispatch(logUserIn(result.token));
            resolve(result);
        })
      } else {
        let error = new Error(response.statusText)
        error.response = response
        dispatch(showError(error.response.statusText), () => {throw error})
        reject(error);
      }
    });
  });
Run Code Online (Sandbox Code Playgroud)

我的Signin.js组件:

 handleSubmit(event) {

    event.preventDefault();

    this.setState({ isLoading: true })

    const { username, password } = this.state;
    this.props.onLoginRequest(username, password, this.props.history).then(result => {
      console.log("Success. Token: "+result.token); //I do get "success" in console
      this.props.history.push('/servers') //Changes address, does not render /servers component
    });

  }

const mapActionsToProps = {
  onLoginRequest: authorization
}
Run Code Online (Sandbox Code Playgroud)

最奇怪的是,如果我将handleSubmit()方法更改为此,则一切运行正常:

  handleSubmit(event) {

    event.preventDefault();

    this.setState({ isLoading: true })

    const { username, password } = this.state;
    this.props.onLoginRequest(username, password, this.props.history).then(result => {
      console.log("Success. Token: "+result.token);
      //this.props.history.push('/servers')
    });
    this.props.history.push('/servers')
  }
Run Code Online (Sandbox Code Playgroud)

如果我尝试从componentWillReceiveProps(newProps)方法推送历史记录,则会出现相同的问题-它会更改地址,但不会呈现新组件。有人可以解释为什么会发生这种情况以及如何解决吗?

谢谢!

小智 6

您需要申请 withRouter 以在每个使用“push”的组件中使用 this.props.history.push('/page')

import { withRouter } from 'react-router-dom';
.....
export default
        withRouter(MoneyExchange);
Run Code Online (Sandbox Code Playgroud)

这在使用推送时很重要。


zil*_*nas 5

如果有人感兴趣-发生这种情况是因为应用程序在推送历史记录之前就已呈现。当我将历史记录推入到动作中,但在将结果转换为JSON之前,它就开始工作,因为现在它会推入历史记录,然后才渲染该应用程序。

export const authorization = (username, password, history) => (dispatch) =>
  new Promise ((resolve, reject) => {
    fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        username: username,
        password: password,
      })
    }).then( response => {
      if (response.ok) {

          //################################
          //This is where I put it

          history.push("/servers");

          //################################

          response.json().then( result => {
            dispatch(logUserIn(result.token));
            resolve(result);
        })
      } else {
        let error = new Error(response.statusText)
        error.response = response
        dispatch(showError(error.response.statusText), () => {throw error})
        reject(error);
      }
    });
  });
Run Code Online (Sandbox Code Playgroud)


Aja*_*mar 5

首先,使用历史包创建一个历史对象:

// src/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Run Code Online (Sandbox Code Playgroud)

然后将其包装在主路由器组件中。

    import { Router, Route, Link } from 'react-router-dom';
    import history from './history';

    ReactDOM.render(
        <Provider store={store}>
          <Router history={history}>
            <Fragment>
              <Header />
              <Switch>
                <SecureRoute exact path="/" component={HomePage} />
                <Route exact path={LOGIN_PAGE} component={LoginPage} />
                <Route exact path={ERROR_PAGE} component={ErrorPage} />
              </Switch>
              <Footer />
            </Fragment>
      </Router>
    </Provider>)         
Run Code Online (Sandbox Code Playgroud)

在这里,发送请求后,重定向到主页。

    function requestItemProcess(value) {
        return (dispatch) => {
            dispatch(request(value));
            history.push('/');
        };

    }   
Run Code Online (Sandbox Code Playgroud)

应该有帮助:)