使用 React Router 在不同页面中呈现组件时出现问题

Problem rendering Component in a different page with React Router

我正在创建一个个人网站来使用 React 进行训练,几天以来我一直无法使用 React Router 渲染组件,就像我将在单击卡片时渲染博客 post .

每次我点击卡片而不是我得到了正确的数据,但它在主页底部,我想在新页面上动态打开它,就像我点击博客文章或一条新闻。

我的卡片组件

  render() {
    const { match } = this.props;

    const { data, value } = this.state;
    return (
      <>
        <div>
          {data.map((job, id) => (
            <div key={id}>
              <div key={job._id} className="blog-card">
                <div className="meta">
                  <div className="photo">
                    <img src={job.img} alt="logo" />{" "}
                  </div>

                </div>
                <div className="description">

                  <p> {job.description}</p>
                  <p className="read-more">
                    <p>{job.location}</p>
                    <p>
                      <span className="apply-job">
                        {" "}
                        <Link
                          className="link-apply"
                          to={{
                            pathname: `${match.url}/${job._id}`,
                            state: job
                          }}
                        >
                         go to {job.workplace_name}
                        </Link>{" "}
                      </span>
                    </p>
                  </p>
                </div>
              </div>
            </div>
          ))}
        </div>
        }
        <Route path={`${match.path}/:_id`} component={Articles} />
      </>
    );
  }
}

当我点击转到 {job.workplace_name} 时,我想在新页面上呈现下面的组件,而不是在我的卡片组件下


const Articles = ({ location }) => (
    <div>
<h1>Hello</h1>
<h1>{location.state.workplace_name}</h1>
<h2>{location.state.position_name}</h2>
<h2>{location.state.description}</h2>
<h2>{location.state.Compensation}</h2>
    </div>
  )

  export default Articles;

当您使用 react-router 编写应用程序代码时,您应该有一个 top-level 组件负责根据您正在访问的 url 决定打印哪个屏幕。

它应该是这样的

import { BrowserRouter } from "react-router-dom";
import { Route, Switch } from "react-router";

const App = () => (
  <Switch>
    <Route exact path="/invoices/dashboard" component={Dashboard} />
    <Route path="/invoices/:id" component={Invoice} />
  </Switch>
);

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  el
);

Switch 组件将仅呈现与当前 URL 匹配的第一个 Route。 如果你不使用它,每条匹配的路由都会被渲染。 这在顶层很有用,可以避免同时拥有两个屏幕(有点像您的问题)。


你最大的问题是你把负责显示博客页面的路由放在你的卡片组件中。

您的组件层次结构:

Router
└ App
   └ Route+Home (maybe)
      └ Card
         └ Route+Articles

它应该是:

Router
└ App
  └ Switch
    ├ Route+Home (maybe)
    │ └ Card
    └ Route+Articles

此外,当您刚开始更改位置 (url) 时,您可以像以前一样使用 Link 组件,或者使用从 Route 组件获得的 history 道具。

在上面的示例中,Dashboard 和 Invoice 得到 "history" 属性。

  • history.push(path) 将模拟导航
  • history.replace(path) 将模拟重定向。

还有更多 https://reacttraining.com/react-router/core/api/history

所以据推测,您有一个看起来像这样或应该像这样的 index.js 文件,您根据解决方案在其中添加了 <BrowserRouter>

import { BrowserRouter } from "react-router-dom";
import { Route, Switch } from "react-router";

const App = () => (
  <Switch>
    <Route exact path="/invoices/dashboard" component={Dashboard} />
    <Route path="/invoices/:id" component={Invoice} />
  </Switch>
);

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  el
);

但是,如果您的 index.js 文件看起来像这样:

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore, applyMiddleware, compose } from "redux";
import reduxThunk from "redux-thunk";

import App from "./components/App";
import reducers from "./reducers";

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducers,
  composeEnhancers(applyMiddleware(reduxThunk))
);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector("#root")

因为您在组件层次结构的 top-level 处创建了一个 index.js 文件,然后创建了一个 App.js 文件,它看起来像这样:

import React from "react";
import { Route } from "react-router-dom";
import Dashboard from "./invoices/Dashboard";
import Invoice from "./invoices/Invoice";
import Header from "./Header";

const App = () => {
  return (
    <div className="ui container">
        <div>
          <Header />
          <Route exact path="/invoices/dashboard" component={Dashboard} />
          <Route path="/invoices/:id" component={Invoice} />
        </div>
    </div>
  );
};

export default App;

在这种情况下,您可以在所有 Route 上使用 exact 关键字并将其全部封装在 <BrowserRouter> 中,并确保将其封装在 <div>就像这样:

import React from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Dashboard from "./invoices/Dashboard";
import Invoice from "./invoices/Invoice";
import Header from "./Header";

const App = () => {
  return (
    <div className="ui container">
      <BrowserRouter>
        <div>
          <Header />
          <Route exact path="/invoices/dashboard" component={Dashboard} />
          <Route exact path="/invoices/:id" component={Invoice} />
        </div>
      </BrowserRouter>
    </div>
  );
};

export default App;