使用 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;
我正在创建一个个人网站来使用 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;