【问题标题】:React Router Link is Showing Two ComponentsReact Router Link 显示两个组件
【发布时间】:2019-11-15 22:53:01
【问题描述】:

我不知道描述这个问题的最佳方式,但我会尽力解释。

在我的核心 React App 组件中,我正在根据用户是否登录进行条件渲染。

如果登录 --- 我显示主页,如果没有,他们会看到登录屏幕。

在我的登录页面上,我试图在底部放置一个链接,引导用户注册一个新帐户。我的问题是,当我单击此“新用户”页面时,它会呈现我的登录表单和创建用户表单,它们都是不同的组件(见下文)。

我怀疑这是我的 react 路由器设置的问题,但我不确定问题是什么。

这是我的 App 组件中的代码。

 <Container>
      <Router>
        <Notification />
        {props.loggedUser ? (
          <div>
            <Navbar />
            <Route exact path="/" render={() => <Blogs />} />
            <Route exact path="/blogs" render={() => <Blogs />} />
            <Route path="/login" render={() => <Login />} />
            <Route
              exact
              path="/blogs/:id"
              render={({ match }) => (
                <Blog
                  blog={blogById(match.params.id)}
                  user={props.loggedUser}
                />
              )}
            />
            <Route exact path="/users" render={() => <Users />} />
            <Route
              exact
              path="/users/:id"
              render={({ match }) => <User user={userById(match.params.id)} />}
            />
          </div>
        ) : (
          <>
            <Login />
          </>
        )}
      </Router>
      <div>
        <br />
        <em>Blog app, John 2019</em>
      </div>
    </Container>

这是我的登录组件。我已经尝试在上面的条件语句的两侧以及下面的登录表单中包含新用户页面的路由,就像我现在所做的那样。所有这些都导致相同的问题。

<h1>Login To Blog Application</h1>
      <Form onSubmit={handleLogin}>
        <Form.Field>
          <label>username</label>
          <input {...username.omitreset} name="username" />
        </Form.Field>
        <Form.Field>
          <label>password</label>
          <input {...password.omitreset} type="password" />
        </Form.Field>
        <Button type="submit">login</Button>
        <div>
          <br />
          <Link to="/newuser">or signup to become a new user</Link>
          <Route path="/newuser" render={() => <NewUser />} />
        </div>
      </Form>
    </>

和 NewUser 组件

import React from "react";
import { connect } from "react-redux";
import { createUser } from "../reducers/userReducer";
import { setNotification } from "../reducers/notificationReducer";
import { Form, Button } from "semantic-ui-react";

const NewUser = props => {
  const addUser = event => {
    event.preventDefault();

    const userObject = {
      username: event.target.username.value,
      name: event.target.name.value,
      password: event.target.password.value
    };

    event.target.username.value = "";
    event.target.name.value = "";
    event.target.password.value = "";
    props.createUser(userObject);
  };

  return (
    <>
      <h1>Create a New Blog Account</h1>
      <Form onSubmit={addUser}>
        <Form.Field>
          <label>username</label>
          <input {...props.username} name="username" />
        </Form.Field>
        <Form.Field>
          <label>name</label>
          <input {...props.name} type="password" />
        </Form.Field>
        <Form.Field>
          <label>password</label>
          <input {...props.password} type="password" />
        </Form.Field>
        <Button type="submit">login</Button>
      </Form>
    </>
  );
};

const mapDispatchToProps = {
  createUser,
  setNotification
};

export default connect(null, mapDispatchToProps)(NewUser);

【问题讨论】:

  • 没有足够的细节来回答这个问题。您还没有告诉我们哪条路线是“新用户”页面,因此通过阅读您的代码进行调试是不可能的。另外,如果用户已经登录,为什么还要在路由中包含登录名?这没有任何意义。
  • 我已经包含了 NewUser 组件,它是为登录表单下方的链接呈现的组件。希望这会有所帮助。我明白你所说的登录路由是什么意思——我仍然对 React Router 感到困惑,这是问题的一部分。
  • 当您点击newuser 路由的链接时,URL 栏会显示什么内容?
  • @JohnRogerson 仍然没有足够的详细信息,因为您根本没有在第一个代码 sn-p 中将 NewUser 组件作为路由安装的任何地方显示。其余的代码在哪里? \
  • @MikeAbeln 它显示了正确的路线 /newuser

标签: javascript reactjs react-router


【解决方案1】:

您不应该进行条件渲染,因为当用户未登录时,Loggin 组件会被渲染并且完全不依赖于路径。然后通过单击 Link to="/newuser" 更改路径,然后在内部呈现 Sign up

【讨论】:

  • 尝试移除条件渲染,将包括 newuser 路由在内的所有路由分组,并使用从 react-router-dom 导出的 Switch 组件包装它们。
  • 感谢您的推荐。我完全按照你说的做了,现在似乎工作正常。我要发布我的代码。可能是一种更好的方式来做我正在做的重定向,但我认为这是一个好的开始。谢谢!
【解决方案2】:

我根据 det2dachoppa 的建议完成了这项工作。去掉了条件,增加了开关和重定向,保证用户不登录就无法查看页面。

 <Router>
    <Notification />
    <div>
      <Navbar />
      <Switch>
        {props.loggedUser && (
          <React.Fragment>
            <Route exact path="/">
              <Blogs />
            </Route>
          </React.Fragment>
        )}
        {props.loggedUser && (
          <React.Fragment>
            <Route exact path="/blogs">
              <Blogs />
            </Route>
          </React.Fragment>
        )}
        {props.loggedUser && (
          <React.Fragment>
            <Route
              exact
              path="/blogs/:id"
              render={({ match }) => (
                <Blog
                  blog={blogById(match.params.id)}
                  user={props.loggedUser}
                  history={props.history}
                />
              )}
            />
          </React.Fragment>
        )}

        {props.loggedUser && (
          <React.Fragment>
            <Route exact path="/users">
              <Users />
            </Route>
          </React.Fragment>
        )}
        {props.loggedUser && (
          <React.Fragment>
            <Route
              exact
              path="/users:id "
              render={({ match }) => (
                <User user={userById(match.params.id)} />
              )}
            />
          </React.Fragment>
        )}
        {props.loggedUser && (
          <React.Fragment>
            <Route exact path="/newblog">
              <NewBlog />
            </Route>
          </React.Fragment>
        )}
        <Route path="/login">
          <Login />
        </Route>
        <Route path="/newuser">
          <NewUser />
        </Route>
        <Redirect to="/login">
          <Login />
        </Redirect>
      </Switch>
    </div>
  </Router>

【讨论】:

  • 一个更好的方法是有条件地渲染 Switch 内部的路由,如下所示:如果用户未登录并且在最后一个路由之后仅添加一个重定向,则呈现。路由排队很重要,因为 Switch 会渲染指向当前路径的第一条路由,但如果用户未登录,则条件会保护这些路由,并且 Switch 将到达重定向。
  • 感谢您跟进此事。我确实接受了您的建议,并在上面重新发布了代码,一切似乎都在工作。希望这就是你的意思!
  • 这就是我的意思!只需对您的代码进行其他调整,您可以使用从 react 导出的 Fragment 组件包装所有依赖于 loggedUser 的路由,并有条件地呈现它,如下所示:{ props.loggedUser && your_protected_routes }。
  • hmm,好吧,我在上面试过这个(代码重新编辑),现在我的 /blogs 和 /users 页面没有显示任何内容,我的 blogs/:id 正在重定向到登录页面.发现任何问题?
  • 我会说是为了可读性,因为您将来可能会添加更多路线
猜你喜欢
  • 2020-01-23
  • 2019-06-18
  • 2017-08-29
  • 1970-01-01
  • 2019-08-11
  • 2016-10-17
  • 2020-12-24
  • 1970-01-01
  • 2018-08-25
相关资源
最近更新 更多