简体   繁体   English

React history.push() 不渲染新组件

[英]React history.push() not rendering new component

I have a React.js project with a simple sign in function.我有一个带有简单登录功能的 React.js 项目。 After the user is authorized, I call history.push method which changes the link in the address bar but does not render the new component.用户获得授权后,我调用 history.push 方法更改地址栏中的链接但不呈现新组件。 (I use BrowserRouter) (我使用浏览器路由器)

My index.js component:我的index.js组件:

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

My Main.js component:我的Main.js组件:

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

export default withRouter(Main);

My Action Creator :我的行动创造者

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

My Signin.js component:我的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
}

The weirdest thing is that if I change my handleSubmit() method to this - everything works perfectly:最奇怪的是,如果我将 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')
  }

The same issue comes if I try to push history from the componentWillReceiveProps(newProps) method - it changes address but does not render new component.如果我尝试从componentWillReceiveProps(newProps)方法推送历史记录,则会出现同样的问题 - 它会更改地址但不会呈现新组件。 Could someone please explain why this happens and how to fix it?有人可以解释为什么会发生这种情况以及如何解决吗?

If anyone is interested - this was happening because the app was rendering before the history was pushed.如果有人感兴趣 - 发生这种情况是因为应用程序在推送历史记录之前正在呈现。 When I put the history push into my action but just before the result is converted into JSON, it started working since now it pushes history and only then renders the App.当我将历史推送放入我的操作中但就在结果转换为 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);
      }
    });
  });

You need to apply withRouter to use this.props.history.push('/page') in every component that use "push"您需要申请 withRouter 以在每个使用“push”的组件中使用 this.props.history.push('/page')

import { withRouter } from 'react-router-dom';
.....
export default
        withRouter(MoneyExchange);

this is important when using push.这在使用推送时很重要。

First, create a history object used the history package:首先,使用 history 包创建一个历史对象:

// src/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();

Then wrap it in in Main Router Component.然后将其包装在主路由器组件中。

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

Here, After dispatching the request, redirecting to home page.在这里,发送请求后,重定向到主页。

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

    }   

should be helpful :)应该有帮助:)

Try to use custom history and Router instead of BrowserRouter.尝试使用自定义历史记录和路由器而不是 BrowserRouter。 After installing history:安装历史记录后:

yarn add history

Create a custom browser history:创建自定义浏览器历史记录:

import { createBrowserHistory } from "history";

export default createBrowserHistory();

Use Router instead of BrowserRouter in your setup:在您的设置中使用 Router 而不是 BrowserRouter:

import history from "your_history_file";

ReactDOM.render(
  <Provider store={createStore(mainReducer, applyMiddleware(thunk))}>
    <Router history={history}>
      <Main />
    </Router>
  </Provider>,
  document.getElementById('root')
);

or if you don't want to use a custom history file and import from there you can crate it directly in your index.js:或者,如果您不想使用自定义历史文件并从那里导入,您可以直接在 index.js 中创建它:

import { createBrowserHistory } from "history";

const history = createBrowserHistory();

ReactDOM.render(
  <Provider store={createStore(mainReducer, applyMiddleware(thunk))}>
    <Router history={history}>
      <Main />
    </Router>
  </Provider>,
  document.getElementById('root')
);

Not Working on this one ->不工作在这个->

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
}

Because in this handleSubmit method you are calling this.props.history.push() inside a promise so the this is pointing to the Promise's instance not your current class instance.因为在这个handleSubmit方法中,你在一个 promise 中调用this.props.history.push()所以this指向的是 Promise 的实例而不是你当前的类实例。

Try this One ->试试这个 - >

 handleSubmit(event) {

    event.preventDefault();
    const { history: { push } } = this.props;
    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
      push('/servers') //Changes address, does not render /servers component
    });
  }

const mapActionsToProps = {
  onLoginRequest: authorization
}

Now In this Statement ->现在在本声明中 ->

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

You are correctly calling this.props.history.push() since it is out of the promise and referring to the Current Class instance.您正确地调用 this.props.history.push() ,因为它超出了承诺并引用了 Current Class 实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM