我使用的React.js应用程序具有以下结构 应对 </跨度> 路由器:
var Dashboard = require(‘./ Dashboard’);var Comments = require(‘./ Comments’);
var Index = React.createClass({ 渲染 - 将一些属性传递给Comments组件。
(通常我会这样做&lt; Comments myprop =“value”/&gt;)
什么是最简单,最正确的方法 应对 </跨度> 路由器? 鈥
对于react-router 2.5.2,解决方案非常简单:
//someConponent ... render:function(){ return ( <h1>This is the parent component who pass the prop to this.props.children</h1> {this.props.children && React.cloneElement(this.props.children,{myProp:'value'})} ) } ...
的 React Router v 4解决方案 强>
我今天早些时候偶然发现了这个问题,这是我使用的模式。希望这对寻求更新解决方案的任何人都有用。
我不确定这是不是 最好 解决方案,但这是我目前的模式。我通常有一个Core目录,我将常用组件与其相关配置(加载器,模态等)保存在一起,并且我包含一个这样的文件:
import React from 'react' import { Route } from 'react-router-dom' const getLocationAwareComponent = (component) => (props) => ( <Route render={(routeProps) => React.createElement(component, {...routeProps, ...props})}/> ) export default getLocationAwareComponent
然后,在相关文件中,我将执行以下操作:
import React from 'react' import someComponent from 'components/SomeComponent' import { getLocationAwareComponent } from 'components/Core/getLocationAwareComponent' const SomeComponent = getLocationAwareComponent(someComponent) // in render method: <SomeComponent someProp={value} />
您会注意到我将组件的默认导出导入为简单的驼峰式案例,它允许我在CamelCase中命名新的,位置感知组件,以便我可以正常使用它。除了附加的导入行和赋值行之外,该组件的行为与预期相同,并且通常会添加所有路径道具。因此,我可以愉快地使用this.props.history.push()从组件生命周期方法重定向,检查位置等。
希望这可以帮助!
现在有一种新的方法来做到这一点,尽管与之前的方法非常相似。
import { Match, Link, Miss } from 'react-router'; import Homepage from './containers/Homepage'; const route = { exactly: true, pattern: '/', title: `${siteTitle} - homepage`, component: Homepage } <Match { ...route } render={(props) => <route.component {...props} />} />
附:这仅适用于alpha版本,并在v4 alpha版本发布后删除。在v4最新,再次,与道路和精确道具。
反应-LEGO 一个示例应用程序包含完全相同的代码 在其react-router-4分支上的routes.js中
这是我提出的最干净的解决方案(React Router v4):
<Route path="/" component={props => <MyComponent {...props} foo="lol" />} />
MyComponent 还有 props.match 和 props.location ,并且 props.foo === "lol" 。
MyComponent
props.match
props.location
props.foo === "lol"
在1.0和2.0中你可以使用 createElement 的支柱 Router 指定如何准确创建目标元素。 文档来源
createElement
Router
function createWithDefaultProps(Component, props) { return <Component {...props} myprop="value" />; } // and then <Router createElement={createWithDefaultProps}> ... </Router>
用无状态函数组件包装它:
<Router> <Route path='/' component={({children}) => <MyComponent myProp={'myVal'}>{children}</MyComponent/> }/> </Router>
对于路由器2.x.
const WrappedComponent = (Container, propsToPass, { children }) => <Container {...propsToPass}>{children}</Container>;
在你的路线......
<Route path="/" component={WrappedComponent.bind(null, LayoutContainer, { someProp })}> </Route>
确保第3个参数是一个像这样的对象: { checked: false } 。
{ checked: false }
你也可以结合使用es6和 无国籍的功能 得到一个更清洁的结果:
import Dashboard from './Dashboard'; import Comments from './Comments'; let dashboardWrapper = () => <Dashboard {...props} />, commentsWrapper = () => <Comments {...props} />, index = () => <div> <header>Some header</header> <RouteHandler /> {this.props.children} </div>; routes = { component: index, path: '/', childRoutes: [ { path: 'comments', component: dashboardWrapper }, { path: 'dashboard', component: commentsWrapper } ] }
用一个 的 自定义路由组件 强> ,这在React Router v3中是可行的。
var Dashboard = require('./Dashboard'); var Comments = require('./Comments'); var routes = ( <Route path="/" handler={Index}> <MyRoute myprop="value" path="comments" handler={Comments}/> <DefaultRoute handler={Dashboard}/> </Route> );
至于 <MyRoute> 组件代码,它应该是这样的:
<MyRoute>
import React from 'react'; import { Route } from 'react-router'; import { createRoutesFromReactChildren } from 'react-router/lib//RouteUtils'; const MyRoute = () => <div><MyRoute> elements are for configuration only and should not be rendered</div>; MyRoute.createRouteFromReactElement = (element, parentRoute) => { const { path, myprop } = element.props; // dynamically add crud route const myRoute = createRoutesFromReactChildren( <Route path={path} />, parentRoute )[0]; // higher-order component to pass myprop as resource to components myRoute.component = ({ children }) => ( <div> {React.Children.map(children, child => React.cloneElement(child, { myprop }))} </div> ); return myRoute; }; export default MyRoute;
有关自定义路径组件方法的更多详细信息,请查看我关于该主题的博客文章: http://marmelab.com/blog/2016/09/20/custom-react-router-component.html
这可能是使用react-handler-dom和cookie处理程序的最佳方法
在index.js中
import React, { Component } from 'react' import {Switch,Route,Redirect} from "react-router-dom" import {RouteWithLayout} from "./cookieCheck" import Login from "../app/pages/login" import DummyLayout from "../app/layouts/dummy" import DummyPage from "../app/pages/dummy" export default ({props})=>{ return( <Switch> <Route path="/login" component={Login} /> <RouteWithLayout path="/dummy" layout={DummyLayout} component={DummyPage} {...props}/> <Redirect from="/*" to="/login" /> </Switch> ) }
并使用cookieCheck
import React , {createElement} from 'react' import {Route,Redirect} from "react-router-dom" import {COOKIE,getCookie} from "../services/" export const RouteWithLayout = ({layout,component,...rest})=>{ if(getCookie(COOKIE)==null)return <Redirect to="/login"/> return ( <Route {...rest} render={(props) => createElement(layout, {...props, ...rest}, createElement(component, {...props, ...rest})) } /> ) }
只是ColCh答案的后续行动。抽象组件的包装非常容易:
var React = require('react'); var wrapComponent = function(Component, props) { return React.createClass({ render: function() { return React.createElement(Component, props); } }); }; <Route path="comments" handler={wrapComponent(Comments, {myprop: value})}/>
我还没有测试过这个解决方案,所以任何反馈都很重要。
重要的是要注意,使用此方法,通过路由器发送的任何道具(例如params)都会被覆盖/删除。
React Router的问题在于它渲染你的组件,因此阻止你传递道具。该 导航路由器 另一方面,您可以渲染自己的组件。这意味着你不必跳过任何箍来传递道具,如下面的代码和随附 的jsfiddle 节目。
var Comments = ({myProp}) => <div>{myProp}</div>; var stateNavigator = new Navigation.StateNavigator([ {key:'comments', route:''} ]); stateNavigator.states.comments.navigated = function(data) { ReactDOM.render( <Comments myProp="value" />, document.getElementById('content') ); } stateNavigator.start();
根据Rajesh Naroth的答案,使用带或不带路由器的组件。
class Index extends React.Component { constructor(props) { super(props); } render() { const foo = (this.props.route) ? this.props.route.foo : this.props.foo; return ( <h1> Index - {foo} </h1> ); } } var routes = ( <Route path="/" foo="bar" component={Index}/> );
或者你可以这样做:
export const Index = ({foo, route}) => { const content = (foo) ? foo : (route) ? route.foo : 'No content found!'; return <h1>{content}</h1> };
你可以通过传递道具 <RouterHandler/> 像这样:
<RouterHandler/>
var Dashboard = require('./Dashboard'); var Comments = require('./Comments'); var Index = React.createClass({ render: function () { var props = this.props; // or possibly this.state return ( <div> <header>Some header</header> <RouteHandler {...props} /> </div> ); } });
这样做的缺点是你不分青红皂白地传递道具。所以 Comments 最终可能会收到真正用于不同组件的道具,具体取决于您的路线配置。从那以后,这不是什么大不了的事 props 是不可变的,但如果两个不同的组件期望一个名为的道具,这可能会有问题 foo 但具有不同的价值观。
Comments
props
foo