【问题标题】:ReactJS redirecting to another page on successful statement not workingReactJS在成功的语句上重定向到另一个页面不起作用
【发布时间】:2022-01-19 02:43:15
【问题描述】:

我正在尝试在反应中创建这个单页应用程序,并且我想根据用户名和密码输入是否正确重定向到另一个页面。我尝试了多种方法,例如

这就是我的 CustomerLoginPage 渲染方法的外观:

  render() {
    return (
     
        <div class="App-header">
          <NavLink to="/main">
            <button id="backButton">Go Back</button>
          </NavLink>
          <h4>Login with your customer account</h4>
          <br />
          <input id="customerLoginUsername" placeholder=" Username"></input>
          <input id="customerLoginPassword" type="password" placeholder=" Password"></input>
          <br />
          <button id="customerLoginButton" onClick={this.handleSubmit}> 
            Login
          </button>
         
  
          <div className="content"></div>
        </div>
     
    );
  }
}
export default withRouter(CustomerLoginPage);

这就是 handleSubmit() 的样子:

handleSubmit() {
    
    let usernameInput = document.getElementById('customerLoginUsername');
    let passwordInput = document.getElementById('customerLoginPassword');
  
    if (usernameInput.value !== 'customer' || passwordInput.value !== 'customer') {
      // alert("Wrong username or password!");
    } else {
      this.props.history.replace('/customerhomepage');
    }
  }

我会在这里遗漏什么?谢谢!

编辑 我设法通过将我的 CustomerLoginPage 从类组件更改为函数组件来解决此问题,然后使用 useHistory 更改页面。 在阅读了有关将路由器用作 HOC 的建议后,我将其从除 index.js 之外的所有文件中删除,并切换到 BrowserRouter 而不是 HashRouter。

这是 CustomerLoginPage 现在的样子:

function CustomerLoginPage () {

  const history = useHistory();

  const loginButtonClicked = () =>{ 
    let path = '/customerhomepage'; 
    history.push(path);
  }

  const backButtonClicked = () => {
    let path = '/main'; 
    history.push(path);
  }

  const handleSubmit = () => {
    
    let usernameInput = document.getElementById('customerLoginUsername');
    let passwordInput = document.getElementById('customerLoginPassword');
  
    if (usernameInput.value !== 'customer' || passwordInput.value !== 'customer') {
      alert("Wrong username or password!");
    } else {
      loginButtonClicked();
    }
  }
  
    return (
     
        <div class="App-header">
  
          <button id="backButton" onClick={backButtonClicked}>Go Back</button>
          <h4>Login with your customer account</h4>
          <br />
          <input id="customerLoginUsername" placeholder=" Username"></input>
          <input id="customerLoginPassword" type="password" placeholder=" Password"></input>
          <br />
          <button id="customerLoginButton" onClick={handleSubmit}> 
            Login
          </button>
         
  
          <div className="content"></div>
        </div>
     
    );
  }

export default withRouter(CustomerLoginPage);

【问题讨论】:

    标签: reactjs react-router


    【解决方案1】:

    当用户单击按钮并触发您的handleSubmit 时,React 组件早已完成渲染,因此从处理程序返回重定向 JSX 不会真正产生任何效果。

    如果您的应用架构支持它(即这不是 SPA),请考虑使用普通的旧 window.location.reload 将用户发送到正确的位置。

    如果不是(我猜你说这是一个 SPA),你将不得不聪明地知道如何让&lt;Redirect&gt; 在下一次渲染中得到处理。反应状态可能是一个好的开始......在你的 else 子句中,不要返回重定向,而是设置一些你的渲染方法可以检查的状态变量,然后渲染 &lt;Redirect&gt; 。 (如果您更改组件的任何状态,您的组件一定会重新渲染。)

    换句话说,根据状态变量的值,修改您的渲染方法以返回它已经执行的操作,或者返回&lt;Redirect&gt;。您可以将状态初始化为null,然后让您的handleSubmit 方法将其更改为例如您要重定向到的URL。然后流程是:渲染登录页面,用户提供错误数据,您的handleSubmit 设置状态这么说,您现在重新渲染为&lt;Redirect&gt; 组件。

    【讨论】:

    • 谢谢,我会试试你说的状态方法!
    【解决方案2】:

    问题

    1. 您不能从异步回调中返回 JSX 并期望它被渲染并生效。 Redirect 必须在组件的返回中呈现。

    2. 使用history 对象不起作用的原因是handleSubmit 处理程序位于路由器之外,提供任何路由上下文进行导航。

    解决方案

    1. 使用history 对象发出命令式重定向。
    2. HashRouter 移动到包装App 并为history 对象提供路由上下文。事实上,您应该只使用一个路由器来包装您的应用以提供路由上下文,因此请移除您的应用中可能拥有的所有其他无关路由器。

    例子:

    index.js

    import { HashRouter as Router } from 'react-router-dom';
    
    ...
    
    ReactDOM.render(
      <React.StrictMode>
        <Router>
          <App/>
        </Router>
      </React.StrictMode>,
      document.getElementById('root')
    );
    

    客户主页

    handleSubmit() {
      const usernameInput = document.getElementById("customerLoginUsername");
      const passwordInput = document.getElementById("customerLoginPassword");
    
      if (usernameInput.value !== "customer" || passwordInput.value !== "customer") {
        // alert("Wrong username or password!");
      } else {
        this.props.history.replace('/customerhomepage');
      }
    }
    

    【讨论】:

    • 我应该在哪里以及如何定义道具?
    • @Ruthless CustomerHomePage 似乎是一个类组件,所以 props 已经在 this.props 上定义了。如果由于某种原因CustomerHomePage 组件没有被Route 组件直接渲染,那么您可以使用withRouter HOC 将history 对象作为道具注入。如果CustomerHomePage 是一个函数组件,那么您可以简单地使用useHistory 钩子。
    • 我用你的例子中的 hashrouter 组件包装了 App,这将是应该在整个应用程序中使用的 HOC 吗?如何调用这个组件?
    • @Ruthless 不,App 只需要 ReactTree 中它上面的路由器,因此它和它渲染的任何东西都可以访问路由上下文(即路由和路由道具)。如果CustomerHomePage 没有在Route 上呈现,那么这就是withRouter HOC 发挥作用的地方。
    • @Ruthless 我在聊天中回复了,但您添加的编辑看起来都不错,除了 Main.js 需要删除 HashRouter,因为 index.js 中已经有一个路由器。
    【解决方案3】:

    由于你使用的是react-router,我建议你使用history api来推送到下一个路由。

    您可以使用 withRouter HOC 为您的道具提供历史 API。

    import { withRouter } from "react-router";
    
    
    handleSubmit() {
      let usernameInput = document.getElementById('customerLoginUsername');
      let passwordInput = document.getElementById('customerLoginPassword');
    
      if (usernameInput.value !== 'customer' || passwordInput.value !== 'customer') {
        // alert("Wrong username or password!");
      } else {
        this.props.history.push('/customerhomepage')
      }
    }
    
    render() {
      return (
        <HashRouter>
          <Switch>
            <Route exact path="/main" component={Main}></Route>
            <Route exact path="/customerhomepage" component={CustomerHomePage}></Route>
          </Switch>
          <div class="App-header">
            <NavLink to="/main">
              <button id="backButton">Go Back</button>
            </NavLink>
            <h4>Login with your customer account</h4>
            <br />
            <input id="customerLoginUsername" placeholder=" Username"></input>
            <input id="customerLoginPassword" type="password" placeholder=" Password"></input>
            <br />
            <button id="customerLoginButton" onClick={this.handleSubmit}>
              Login
            </button>
    
            <div className="content"></div>
          </div>
        </HashRouter>
      );
    }
    
    export default withRouter(CustomerLoginPage);
    

    编辑:

    正如其他人指出的那样,您需要将 HashRouter 组件提升到更高的组件,以便 withRouter 工作。

    【讨论】:

      猜你喜欢
      • 2018-01-04
      • 2019-03-31
      • 2020-06-12
      • 1970-01-01
      • 1970-01-01
      • 2020-08-29
      • 1970-01-01
      • 2018-04-29
      • 2013-08-13
      相关资源
      最近更新 更多