【问题标题】:React router is not rendering single id routes on refreshReact 路由器不会在刷新时呈现单个 id 路由
【发布时间】:2019-07-12 11:32:30
【问题描述】:

我正在做一个个人项目,几天以来我一直被反应路由器问题困扰。

我正在获取 API 并尝试使用单个 id 呈现路由,因此当我单击卡片链接时一切正常,但是一旦尝试在新选项卡上手动呈现链接,例如我得到了控制台错误

TypeError: Cannot read property 'position_name' of undefined

 | const Articles = ({ location }) => (
  5 |   <ArticleComponent
> 6 |     position_name={location.state.position_name}
  7 |     workplace_name={location.state.workplace_name}

这是我在 APP.js 文件中的路线

    <Switch>
      <Route exact path="/" component={JobCard} />
      <Route path="/jobs/:_id" component={Articles} />
    </Switch>

以及我获取卡片的组件。

  <div key={job._id} className="blog-card">
                    <div className="description">
                      <Link
                        className="link-apply"
                        to={{
                          pathname: `/jobs/${job._id}`,
                          state: job
                        }}
                      >
                        <h5 className="position-name">{job.position_name}</h5>
                        <p className="place">{job.workplace_name}</p>
                        <p className="location-job">{job.location}</p>
                      </Link>
                    </div>

所以我想要实现的是能够在我手动输入链接时呈现文章,例如:http://localhost:3000/jobs/5ccc770c6ac54350001f0954

但由于某些原因,它仅在我单击卡片时才会呈现。

提前感谢您的帮助

【问题讨论】:

  • 我不使用 React Router,但我感觉状态可能是使用历史状态来存储它,这对新窗口无效。尝试改用查询参数。
  • 您的 .htaccess 似乎有问题
  • 我认为这是因为我无法刷新状态,但我不知道如何以任何其他方式解决此问题,当我在邮递员中获取单个 id 时它正在工作
  • 当通过点击您的卡片调用您的页面时,您在 &lt;Link&gt; 组件中设置状态:state: job。但是当输入你的 url 时,你并没有发送所需的附加信息(你的 state 键),所以你的组件无法读取它(实际上它是未定义的)。如果您需要通过键入 url 来发送信息,则该信息必须包含在 URL 参数中,或者可以通过 URL 参数访问。因此,您的position_nameworkplace_name 必须与job_id 一起在您的URL 中,或者job_id 必须允许您执行某种数据库查询来获取这些信息。
  • 你知道我怎么能做到这一点,因为我现在很迷茫,我可以通过我的数据库中的单个 id 访问元素

标签: javascript reactjs react-router react-router-v4


【解决方案1】:

但由于某些原因,它仅在我单击卡片时才会呈现。

当您点击卡片中的&lt;Link&gt; 时,您会看到您的请求如下所示:

<Link
  className="link-apply"
  to={{
    pathname: `/jobs/${job._id}`,
    state: job
  }}
>

执行此操作时,您的请求包含 2 条信息:

  1. 它想去pathname的路径
  2. 它会发送一个包含您的job 值的状态

所以在你的组件中

const Articles = ({ location }) => (
  <ArticleComponent
    position_name={location.state.position_name}
    workplace_name={location.state.workplace_name}
    . . .
  />
);

location 对象如下所示:

location = {
  pathname: ‘your_url’,
  state: {
    position_name: ‘your_string’,
    workplace_name: ‘your_string’
    . . .
  }
}

这就是调用location.state.position_name 有效的原因。但是,当您手动输入 URL 时,位置只会如下所示:

location = {
  pathname: ‘your_url’
}

因为,你实际上没有通过任何状态!这是不可能实现的,你不能通过输入你的 URL 来向你的位置道具添加任何东西。所以,让我们开始工作吧。

解决方案

您需要另一种方式来获取您的状态信息。由于您可以从数据库中检索任何内容,因此应该执行以下操作。只需更改您的 &lt;Article&gt; 组件:

Article.js

// You can pass the whole props or destructure the ones you need
// like you did before. In my example, I don’t nee anything so I
// just leave it blank
const Articles = () => {
  // Not the best method but it works everywhere, since I don’t know
  // your whole project structure. Read below for more information.
  const pathname = window.location.pathname.split(‘/‘);
  const job_id = pathname[pathname.length - 1];

  // Make your query here
  // Assume query() is a function that return a job with given id
  // from your database
  const job = query(job_id);
  let position_name;
  let workplace_name;

  // If query was successful
  if (job) {
    position_name = job.position_name;
    workplace_name = job.workplace_name;
  }

  return (
    <ArticleComponent
      position_name={position_name}
      workplace_name={workplace_name}
      . . .
    />
  );
};

因此,您无需任何其他信息即可检索所需的信息,而不需要您的 job_id,并且您允许用户从直接 URL 进行查询。

关于路径名的注意事项

我从window.location 检索到job_id,这是一个默认的javascript URL 解析器。但是,它有点难看,更不用说它的可扩展性了。

根据您的项目树的结构,如果您的元素附加到路由器,您可以使用 query_string 库,如 this topic 中所述(注意一些在最近的 React 版本中不再有效的方法) .

由于您的用户可能会出错(例如,输入不存在的 id),因此您需要处理查询中的错误,例如通过返回空值或重定向到 404 if 查询没有成功。

【讨论】:

  • 感谢您提供有据可查的答案!现在对我来说有点道理,但我仍然不明白我应该在这里传递什么 ``` // 在此处进行查询 const position_name = myDatabase.query('your_id_and_everything'); const workspace_name = myDatabase.query('your_id_and_everything');``` 我使用的是 noSQL 数据库,所以我得到了一个从 Heroku 获取的链接
  • @Ron 如果你有一个函数query(id),它返回给定id 的作业。假设这个函数返回一个对象:{id: 1, position_name: ‘employee’, …}。您会在变量中得到结果:const myJob = query(1);。然后,您可以像这样分配您的position_nameconst position_name = myJob.position_name;... 或直接使用myJob.position_name。我写这个是因为我不知道你如何查询你的数据库。 Position_name 在这里的值为“employee”
  • @Ron 刚刚编辑了我的答案,以便看起来更清晰
猜你喜欢
  • 2021-09-11
  • 1970-01-01
  • 2021-01-16
  • 2019-11-13
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 2020-12-02
  • 2018-08-19
相关资源
最近更新 更多