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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50925939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 09:20:15  来源:igfitidea点击:

React history.push() not rendering new component

javascriptreactjsreact-router-v4

提问by zilijonas

Good day, everybody!

大家好!

I have a React.js project with a simple sign in function. 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. (I use BrowserRouter)

我有一个带有简单登录功能的 React.js 项目。用户获得授权后,我调用 history.push 方法更改地址栏中的链接但不呈现新组件。(我使用浏览器路由器)

My index.jscomponent:

我的index.js组件:

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

My Main.jscomponent:

我的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.jscomponent:

我的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. Could someone please explain why this happens and how to fix it?

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

Thank you!

谢谢!

采纳答案by zilijonas

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

回答by FP Angiosty

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.

这在使用推送时很重要。

回答by Ajay Kumar

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

应该有帮助:)

回答by Harish Soni

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
}

Becuase in this handleSubmitmethod you are calling this.props.history.push() inside a promise so the thisis 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 实例。

回答by devserkan

Try to use custom history and Router instead of BrowserRouter. After installing history:

尝试使用自定义历史记录和路由器而不是 BrowserRouter。安装历史记录后:

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