无状态组件 React 路由器
Posted
技术标签:
【中文标题】无状态组件 React 路由器【英文标题】:Stateless component React router 【发布时间】:2018-11-26 11:33:24 【问题描述】:我是 React 和 Redux 的新手,我实际上是在创建自己的代码,但我被无状态组件中的路由器之类的东西卡住了。
所以,实际上我需要使用 this.props.history.push('/somepath') 来路由到一个组件。这不会发生在无状态组件内部。
我的无状态组件是
import React from "react"; // eslint-disable-line no-unused-vars
import "bootstrap/dist/css/bootstrap.min.css";
import "./header.css";
const Header = () => (
handleAuthor()
this.props.history('/somepath')// this is not working
,
render()
return (
<div className = "header">
<h1 onClick = this.handleAuthor.bind(this)>this.props.headerText</h1>
</div>
);
);
export default Header;
我在另一个无状态组件(如 mainlayout)中调用它
import React from "react"; // eslint-disable-line no-unused-vars
import Header from "../header/Header"; // eslint-disable-line no-unused-vars
import Footer from "../footer/Footer"; // eslint-disable-line no-unused-vars
import "./mainLayout.css";
const MainLayout = props => (
render()
return (
<div className="App">
<Header headerText = "RK Boilerplate"/>
<div className = "mainLayout">
<main>props.children</main>
</div>
<Footer />
</div>
);
);
export default MainLayout;
我的主文件 index.js 是这样的
import React from "react"; // eslint-disable-line no-unused-vars
import ReactDOM from "react-dom"; // eslint-disable-line no-unused-vars
import matchRoutes, renderRoutes from "react-router-config"; // eslint-disable-line no-unused-vars
import Router from "react-router-dom"; // eslint-disable-line no-unused-vars
import Switch from "react-router"; // eslint-disable-line no-unused-vars
import Provider from "react-redux"; // eslint-disable-line no-unused-vars
import store from "./store"; // eslint-disable-line no-unused-vars
import routes from "./routes"; // eslint-disable-line no-unused-vars
import MainLayout from "./components/mainLayout/MainLayout"; // eslint-disable-line no-unused-vars
import createHistory from "history/createBrowserHistory";
let history = createHistory();
const App = document.getElementById("app");
export default App;
ReactDOM.render(
<Provider store=store>
<MainLayout>
<Router history= history>
<Switch>
renderRoutes(routes)
</Switch>
</Router>
</MainLayout>
</Provider>,
App);
所以我需要的是我必须从标头路由到另一个组件,该组件和路径在路由器文件中给出
路由器.js
import Home from "../containers/Home";
import About from "../containers/About";
import CreateUser from "../containers/CreateUser";
import Layout from "../containers/Layout";
const routes = [
path: "/",
exact: true,
component: Layout
,
path: "/home",
exact: true,
component: Home
,
path:"/About",
exact: true,
component: About
,
path:"/createUser",
exact: true,
component: CreateUser
];
export default routes;
当我尝试从标头进行路由时,出现类似 push of undefined 的错误。 我错过了什么吗?我应该在这里做些什么改变。
提前致谢。
【问题讨论】:
您可能已经知道这一点,但您没有将props
传递到您的Header
组件中,这就是您得到未定义错误的原因。您可以这样尝试:const Header = (props) => ...
,然后通过props.history
(没有this
)访问您的history
。您还可以使用解构使其内部看起来更干净。
【参考方案1】:
您可以直接导入历史对象并从中推送。例如尝试下面的代码。
import React from "react"; // eslint-disable-line no-unused-vars
import "bootstrap/dist/css/bootstrap.min.css";
import "./header.css";
import history from "/your/history/path" //try this
const Header = () => (
handleAuthor()
history.push('/somepath')// change to this
,
render()
return (
<div className = "header">
<h1 onClick = this.handleAuthor.bind(this)>this.props.headerText</h1>
</div>
);
);
export default Header;
像下面这样创建浏览器历史记录,并通过导入在任何地方使用它。
import createBrowserHistory from 'history/createBrowserHistory';
export default createBrowserHistory();
【讨论】:
这行不通,因为它会改变 URL,但组件不会被渲染 我不知道你的意思,但是当我使用它时它工作得很好 我更新了答案。看看这是否适合你。 - 我一直这样做 能否请您粘贴代码让我检查,我不知道我在这里缺少什么 检查这个 repo。 github.com/serendipity1004/MERN-stack-boilerplate 历史文件位于client/services/history.js
。正在client/containers/App.js
进行导入。您可以对任何其他组件使用完全相同的导入来移动路由并渲染组件【参考方案2】:
希望这不会来得太晚。我可以成功地从有状态组件重定向,但我想将我的组件转换为无状态组件,因为唯一使它成为有状态的是重定向位。我对反应还很陌生,而且那里的大多数资源都不是很清楚。我就是这样做的。
import React from "react"; // eslint-disable-line no-unused-vars
import "bootstrap/dist/css/bootstrap.min.css";
import "./header.css";
const Header = (props) =>
return (
<div className = "header">
<h1 onClick = props.history.push('/some-path')>props.headerText</h1>
</div>
);
export default Header;
【讨论】:
【参考方案3】:使用 withRouter 对我有用,(加上忽略打字稿警告):
import withRouter from 'react-router-dom';
...
type Props = myProp: boolean ;
// @ts-ignore
export const MyComponent: FC<Props> = withRouter(( myProp, history ) =>
...
)
【讨论】:
【参考方案4】:2019 年,React Router v4 现在为无状态/函数式组件添加了 useHistory 钩子:
https://reacttraining.com/react-router/web/api/Hooks/usehistory
来自文档:
import useHistory from "react-router-dom";
function HomeButton()
let history = useHistory();
function handleClick()
history.push("/home");
return (
<button type="button" onClick=handleClick>
Go home
</button>
);
【讨论】:
谢谢,但我收到此错误。尝试导入错误:“useHistory”未从“react-router-dom”导出。我使用 "react": "^16.9.0", "react-router-dom": "^5.0.1", 不幸的是,它仅在 5.1 中添加(reacttraining.com/blog/react-router-v5-1/#usehistory)。 奇怪的是这种方法不起作用。我正在使用 React 路由器 5,我的 React 版本是 16+。地址更改但组件未呈现!以上是关于无状态组件 React 路由器的主要内容,如果未能解决你的问题,请参考以下文章
React Typescript:添加位置状态以响应路由器组件
如何在 nextjs 的 getInitialProps 无状态组件中访问路由器参数
在组件之间路由时如何保持 React 新的 Context API 状态?