[javascript] react-router - تمرير الدعائم إلى مكون معالج


9 Answers

إذا كنت تفضل عدم كتابة أغلفة ، أعتقد أنك تستطيع القيام بذلك:

class Index extends React.Component { 

  constructor(props) {
    super(props);
  }
  render() {
    return (
      <h1>
        Index - {this.props.route.foo}
      </h1>
    );
  }
}

var routes = (
  <Route path="/" foo="bar" component={Index}/>
);
Question

لدي البنية التالية لتطبيق React.js الخاص بي باستخدام React Router :

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');

var Index = React.createClass({
  render: function () {
    return (
        <div>
            <header>Some header</header>
            <RouteHandler />
        </div>
    );
  }
});

var routes = (
  <Route path="/" handler={Index}>
    <Route path="comments" handler={Comments}/>
    <DefaultRoute handler={Dashboard}/>
  </Route>
);

ReactRouter.run(routes, function (Handler) {
  React.render(<Handler/>, document.body);
});

أرغب في تمرير بعض الخصائص إلى مكون Comments .

(عادةً سأفعل هذا مثل <Comments myprop="value" /> )

ما هي الطريقة الأسهل والأسهل للقيام بذلك مع React Router؟




React-router v4 alpha

الآن هناك طريقة جديدة ، للقيام بذلك ، على الرغم من مشابهة جدا للطريقة السابقة.

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} />} />

سكرتير خاص هذا يعمل فقط في إصدار ألفا ، وتمت إزالتها بعد الإصدار ألفا v4. في V4 الأحدث ، هو مرة أخرى ، مع المسار والدعائم الدقيقة.

react-lego يحتوي أحد الأمثلة على تطبيق يحتوي على تعليمات برمجية تفعل ذلك بالضبط في ways.js على فرع react-router-4 الخاص به




يمكنك أيضًا دمج دالات es6 و noneless للحصول على نتيجة أنظف بكثير:

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 4.

سيكون رمز مثل هذا:

<Route path="comments" render={(props) => <Comments myProp="value" {...props}/>}/>

لاحظ أنني استخدم render بدلاً من component . والسبب هو تجنب إعادة ربط غير مرغوب فيها . أنا أيضا تمرير props إلى هذه الطريقة ، وأنا استخدم نفس الدعائم في عنصر التعليقات مع عامل انتشار الكائن (اقتراح ES7).




يمكنك تمرير الدعائم عبر <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 ولكن بقيم مختلفة.




React Router v 4 solution

تعثرت على هذا السؤال في وقت سابق اليوم ، وهنا هو النمط الذي استخدمه. نأمل أن يكون هذا مفيدًا لأي شخص يبحث عن حل أكثر حداثة.

لست متأكدًا إذا كان هذا هو الحل الأفضل ، لكن هذا هو النمط الحالي لهذا. لدي عادةً دليل أساسي حيث أحافظ على مكونات شائعة الاستخدام مع التكوينات ذات الصلة (اللوادر ووحدات التحكم وما إلى ذلك) ، وأقوم بتضمين ملف مثل هذا:

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 () ، والتحقق من الموقع ، وما إلى ذلك.

أتمنى أن يساعدك هذا!




لفها بمكون وظيفة عديمة الحالة:

<Router>
  <Route 
    path='/' 
    component={({children}) => 
      <MyComponent myProp={'myVal'}>{children}</MyComponent/>
    }/>
</Router>



يمكنك تمرير الدعائم بتمريرها إلى <RouteHandler> (في v0.13.x) أو مكون التوجيه نفسه في الإصدار 1.0 ؛

// v0.13.x
<RouteHandler/>
<RouteHandler someExtraProp={something}/>

// v1.0
{this.props.children}
{React.cloneElement(this.props.children, {someExtraProp: something })}

(من دليل الترقية على https://github.com/rackt/react-router/releases/tag/v1.0.0 )

سيحصل جميع المتعاملين مع الأطفال على نفس مجموعة الدعامات - قد يكون ذلك مفيدًا أو لا يعتمد على الظروف.




استخدم المكون مع أو بدون جهاز التوجيه استنادًا إلى إجابة 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>
};



باستخدام مكون مسار مخصص ، هذا ممكن في 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>&lt;MyRoute&gt; 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




Related