react-router - ส่งอุปกรณ์ประกอบฉากไปยังตัวจัดการ


315

ฉันมีโครงสร้างต่อไปนี้สำหรับแอปพลิเคชัน 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


ปัญหาที่นี่และในกรณีที่คล้ายกันโดยเฉพาะอย่างยิ่งกับเฟรมเวิร์กหรือ libs ที่เขียนในบางภาษาการขาดการผสมผสาน (MoC) แบบดั้งเดิมดูเหมือนว่าตกลงในการตอบสนองพวกเขาค่อนข้างดีการกำหนดองค์ประกอบด้วยแบบดั้งเดิมในองค์ประกอบการทำปฏิกิริยาและองค์ประกอบMoCซึ่งดูเหมือนว่าตกลงเช่นกันในการตอบสนอง แต่วิธีการรวมกันไม่สมบูรณ์ หนึ่งจะต้องสามารถส่งอุปกรณ์ประกอบฉากไปยังส่วนประกอบในขณะที่การรวมส่วนประกอบไปยังอีกองค์ประกอบไม่สำคัญว่าโดยการวางองค์ประกอบหนึ่งในองค์ประกอบอื่นเป็นลูกของมันหรือผ่านองค์ประกอบหนึ่งเป็นอุปกรณ์ไปยังอีก
Selçuk

ด้วยไวยากรณ์บางอย่างเช่น <ComponentA x={<ComponentB y={<ComponentC z={} />} />} /> OR <ComponentA x={ComponentB(ComponentC()) } /> มิฉะนั้นปัญหานี้ของการรวมกันของ abstractionsจะเกิดขึ้นอีกและจะต้องมีการแก้ปัญหาที่ดีที่สุดและทางอ้อมน้อยกว่าที่เรียกว่าวิธีการแก้ปัญหาเช่นการห่อ ฯลฯ ฯลฯ Abstractions ต้องเป็นพลเมืองชั้นหนึ่ง
Selçuk

คำตอบ:


152

UPDATE

ตั้งแต่รีลีสใหม่มีความเป็นไปได้ที่จะส่ง props โดยตรงผ่านRouteส่วนประกอบโดยไม่ต้องใช้ Wrapper ตัวอย่างเช่นโดยใช้renderเสาไม้ค้ำยัน

ส่วนประกอบคือ:

class Greeting extends React.Component {
  render() {
    const {text, match: {params}} = this.props;

    const {name} = params;

    return (
      <React.Fragment>
        <h1>Greeting page</h1>
        <p>
          {text} {name}
        </p>
      </React.Fragment>
    );
  }
}

การใช้งาน:

<Route path="/greeting/:name" render={(props) => <Greeting text="Hello, " {...props} />} />

ตัวอย่าง Codesandbox


เวอร์ชั่นเก่า

วิธีที่ฉันชอบคือห่อ Commentsส่วนประกอบและส่ง wrapper เป็นตัวจัดการเส้นทาง

นี่คือตัวอย่างของคุณเมื่อมีการเปลี่ยนแปลง:

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

var CommentsWrapper = React.createClass({
  render: function () {
    return (
      <Comments myprop="myvalue"/>
    );
  }
});

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

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

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

58
ฉันพบปัญหาเดียวกัน แต่วิธีนี้ไม่ได้แก้ปัญหาได้อย่างรวดเร็วหรือไม่
captDaylight

8
เห็นด้วยกับ captDaylight มันจะกลายเป็น verbose ต้องการวิธีที่ดีกว่าในการจัดการกับสิ่งนี้!
Mattias Hallström

6
@mattiashallstrom IMO วิธีที่ดีกว่าใน 1.0 คือการเพิ่มคุณสมบัติให้กับเส้นทาง ดูคำตอบของ Thomas E
k00k

28
คุณสามารถเพิ่มไวยากรณ์องค์ประกอบไร้สัญชาติ (เพียงแลมบ์ดา) นอกจากนี้ยังมีก็สวยสั้น<Route path="comments" component={() => (<Comments myProp="value" />)}/>
Ciantic

33
ฉันจะไม่เห็นด้วยกับการสร้างองค์ประกอบเพิ่มเติมเพียงผ่านคุณสมบัติที่เป็น "วิธีที่ต้องการ" มันละเอียดซับซ้อนผิดพลาดได้ง่ายและผิดไปในทางที่เป็นไปได้ อาจเป็นวิธีเดียวที่เราเตอร์ตอบกลับอนุญาต แต่การเรียกว่า "โปรดปราน" เป็นการยืดออก ต้องการโดยใคร
Szczepan Hołyszewski

260

หากคุณไม่อยากเขียนคำว่า wrapper ฉันคิดว่าคุณสามารถทำได้:

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

11
นี่คือคำตอบที่ถูกต้อง ใน react-router 1.0 คุณสามารถรับrouteวัตถุธรรมดาในส่วนประกอบของคุณ นี่คือคำตอบของปัญหา
Github

4
นี่คือคำตอบง่ายๆที่ฉันกำลังมองหา เทคนิคอื่น ๆ ใช้งานได้ แต่ต้องใช้จำนวน 10 เท่าของรหัส ทำงานได้ดีสำหรับ v1.0.x ข้อเสียเดียวที่ฉันเห็นคือถ้าคุณตั้งใจจะใช้ส่วนประกอบเดียวกันทั้งที่มีและไม่มีคอนเทนเนอร์เราเตอร์ แต่สำหรับฉันส่วนประกอบระดับบนสุดทั้งหมดของฉันแมป 1 ต่อ 1 กับเส้นทาง
killthrush

12
เยี่ยมมากขอบคุณ! หากใครสงสัยก็จะเห็นว่าคุณสมบัติของ foo นั้นมีอยู่ในองค์ประกอบของคุณดังนี้: this.props.route.foo
k00k

8
สามารถตั้งค่านี้เป็นคำตอบที่ถูกต้องเพื่อหลีกเลี่ยงความสับสนหรือไม่
Archibald

2
Nope! ดูคำตอบของ Rajesh Naroth สำหรับการแก้ปัญหาที่แท้จริง :)
อเล็กซ์

114

คัดลอกจากความคิดเห็นโดยcianticในการตอบรับที่ยอมรับ:

<Route path="comments" component={() => (<Comments myProp="value" />)}/>

นี่เป็นทางออกที่งดงามที่สุดในความคิดของฉัน มันได้ผล. ช่วยฉันด้วย


นี่เป็นพื้นเหมือนกับคำตอบของ wrapper ด้านบน แต่มันพูดน้อยกว่ามาก แม้ว่ามนุษย์ไวยากรณ์นั้นจะดูด ลองขว้างใน a_ref
EdH

11
มันเหมือนเสื้อคลุมที่ไม่ระบุชื่อดังนั้นอุปกรณ์ประกอบฉากแบบฉีดทั้งหมด (เช่นตำแหน่ง) จะพลาด เราต้องผ่านฉากประกอบฉากด้วยตนเองเช่นกันcomponent={(props) => (<Comments myProp="value" location={ props.location } />)}แต่มันก็ยุ่งเหยิงอีกครั้ง
yuji

1
@JacobThomason เราไม่แสดงปฏิกิริยาการกำหนดค่าเราเตอร์อีกครั้งดังนั้นจึงไม่น่าจะเป็นการลงโทษประสิทธิภาพ
Sebastien Lorber

9
ตั้งแต่ React-Router 4 หากคุณมีฟังก์ชั่นแบบอินไลน์คุณจะได้รับการแจ้งเตือนที่ไม่ต้องการจำนวนมาก สำหรับการเรนเดอร์อินไลน์ให้ใช้การเรนเดอร์ prop เชื่อมโยงไปยังเอกสาร
Daniel Reina

1
@yuji เพื่อไม่ให้ยุ่งเกินไปใครสามารถทำได้component={(props) => (<Comments {...props} myProp="value" />)}เพื่อรักษาอุปกรณ์ฉีดที่ถูกต้อง
apelsinapa

57

นี่คือวิธีการแก้ปัญหาจาก Rajeshโดยไม่ต้องแสดงความคิดเห็นไม่สะดวกโดย Yujiและปรับปรุงสำหรับ React Router 4

รหัสจะเป็นดังนี้:

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

โปรดทราบว่าผมใช้แทนrender componentเหตุผลก็คือการหลีกเลี่ยงremounting ที่ไม่พึงประสงค์ ฉันส่งต่อpropsไปยังวิธีการนั้นและฉันใช้อุปกรณ์ประกอบฉากเดียวกันกับองค์ประกอบความคิดเห็นกับตัวดำเนินการกระจายวัตถุ (ข้อเสนอ ES7)


ยอดเยี่ยมมาก ๆ ด้วยการแก้ปัญหาการติดตั้งที่ไม่พึงประสงค์เช่นกัน! +1
GLindqvist

44

เพียงติดตามคำตอบของ 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) จะถูกเขียนทับ / ลบออก


1
บ๊อบคุณคุ้นเคยกับการปิดหรือไม่? stackoverflow.com/questions/111102/…
sigmus

3
และถ้าคุณต้องการreturn React.createElement(Component, _.assign({}, this.props, props));คิวรี่และ params จากเราเตอร์เช่นกันสิ่งนี้จะใช้งานได้: (อันนี้ใช้ _.assign เพื่อสร้างออบเจกต์รวม ... วิธีอื่นมีให้ใช้)
Malcolm Dwyer

2
คุณอาจต้องการผ่านเด็ก ๆ ด้วย | var wrapComponent = ฟังก์ชั่น (ส่วนประกอบอุปกรณ์ประกอบฉาก) {return React.createClass ({render: function () {return React.createElement (ส่วนประกอบอุปกรณ์ประกอบฉาก this.props.children);}}); };
Julio Rodrigues

1
นี่คือส่วนประกอบการสั่งซื้อที่สูงขึ้นสำหรับผู้ที่ไม่คุ้นเคยกับพวกเขาfacebook.github.io/react/docs/higher-order-components.html
icc97

1
NB นี่สำหรับ React Router เวอร์ชันเก่าทันที v4 ปัจจุบันมีrender, componentและวิธีการในการchildren Routeโปรดทราบว่าเมื่อ@dgrcode ตอบคะแนนคุณควรใช้renderแทนcomponent
icc97

31

คุณสามารถส่งอุปกรณ์ประกอบฉากโดยส่งผ่านไปยัง<RouteHandler>(ใน v0.13.x) หรือส่วนประกอบเส้นทางใน v1.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 )

ตัวจัดการเด็กทั้งหมดจะได้รับอุปกรณ์ประกอบฉากชุดเดียวกันซึ่งอาจมีประโยชน์หรือไม่ขึ้นอยู่กับสถานการณ์


1
มันเป็นปริศนาที่จะเห็นว่ามันReact.cloneElementถูกส่งผ่านหลาย ๆ องค์ประกอบ แต่ฟังก์ชั่นลายเซ็นดูเหมือนว่าจะมีเพียงหนึ่งองค์ประกอบการตอบสนอง ฉันคิดว่าข้อมูลโค้ดนี้สามารถทำให้เข้าใจง่ายขึ้น
มนู

2
นี่เป็นคำตอบที่ชัดเจนที่สุดสำหรับเป้าหมายของเอกสาร แต่ฉันก็เห็นด้วยกับมนูว่ามันสามารถเขียนเพื่อแสดงการใช้ที่ดีขึ้น รหัสเฉพาะเจาะจงมากขึ้นสำหรับคำถามจะมีลักษณะเช่น: React.cloneElement(this.props.children, {myprop: "value"})หรือReact.cloneElement(this.props.children, {myprop: this.props.myprop})อื่น ๆ
juanitogan

คำตอบนี้ชนะ นอกจากนี้ยังมีความชัดเจนมากขึ้นว่าเกิดอะไรขึ้นในสิ่งที่เราท์เตอร์ทำเพื่อคุณ ในขณะที่มีคนอ่านรหัสถ้าฉันรู้ว่าคอมเม้นท์อยู่ในดัชนีฉันจะดูดัชนีเพื่อดูว่าอุปกรณ์ประกอบฉากใดถูกส่งไปยังความคิดเห็น หากฉันรู้ว่าความคิดเห็นเป็นตัวจัดการเราเตอร์ฉันจะดูการกำหนดค่าเราเตอร์และค้นหาความคิดเห็นที่ผู้ปกครองของดัชนีและยังคงไปดูที่นั่น
mjohnsonengr

24

การใช้ ES6 คุณสามารถสร้างส่วนประกอบห่อหุ้มแบบอินไลน์ได้:

<Route path="/" component={() => <App myProp={someValue}/>} >

หากคุณต้องการส่งลูก:

<Route path="/" component={(props) => <App myProp={someValue}>{props.children}</App>} >


นี่เป็นสิ่งที่ดี แต่มันไม่ผ่านเด็ก ๆ ในกรณีที่มี
เมษายน

@zpr ฉันได้เพิ่มตัวอย่างสำหรับ props.children
Nick

2
ตามที่@dgrcode ตอบคุณควรใช้renderแทนcomponent
icc97

23

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

PS สิ่งนี้ทำงานได้ในเวอร์ชันอัลฟ่าเท่านั้นและถูกลบออกหลังจากรุ่น v4 alpha ใน v4 ล่าสุดเป็นอีกครั้งกับเส้นทางและอุปกรณ์ประกอบฉากที่แน่นอน

react-legoตัวอย่างแอปประกอบด้วยรหัสที่ทำสิ่งนี้อย่างแน่นอนใน route.js บน react-router-4


21

นี่คือทางออกที่สะอาดที่สุดที่ฉันได้รับ (React Router v4)

<Route
  path="/"
  component={props => <MyComponent {...props} foo="lol" />}
/>

MyComponentยังคงมีprops.matchและและมีprops.locationprops.foo === "lol"


13

ห่อด้วยองค์ประกอบฟังก์ชั่นไร้สัญชาติ:

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

12

คุณสามารถใช้ RouteHandler mixin เพื่อหลีกเลี่ยงองค์ประกอบของ wrapper และง่ายต่อการส่งผ่านสถานะของผู้ปกครองเป็นอุปกรณ์ประกอบฉากได้ง่ายขึ้น:

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var RouteHandler = require('react-router/modules/mixins/RouteHandler');

var Index = React.createClass({
      mixins: [RouteHandler],
      render: function () {
        var handler = this.getRouteHandler({ myProp: 'value'});
        return (
            <div>
                <header>Some header</header>
                {handler}
           </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);
});

1
มันเปิดเผยต่อสาธารณชนเกี่ยวกับการสร้างร่มทั่วโลกในฐานะ ReactRouter.RouteHandlerMixin ดังนั้นฉันจึงไม่คิดอย่างนั้น
กรกฎาคม

สิ่งนี้ยังช่วยในการทำอนิเมชั่นการเปลี่ยนภาพโดยใช้ TransitionGroup และ CSSTransitionGroup ซึ่งฉันไม่สามารถใช้งานได้โดยใช้วิธี wrapper
กรกฎาคม

2
เป็นเรื่องแปลกที่ไม่มีการกล่าวถึงในเอกสารทางการ
Kosmetika

Mixins ไม่ได้รับการแนะนำจาก React docs อีกต่อไป: facebook.github.io/react/blog/2016/07/13/…
icc97

12

คุณสามารถส่งผ่านอุปกรณ์ประกอบฉากผ่านทาง<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แต่มีค่าแตกต่างกัน


1
3 จุด / จุดทำอะไรหรือหมายถึงอะไรในรหัสนี้:{...props}
Giant Elk

2
ฉันเดาว่า Flux จะหลีกเลี่ยงความจำเป็นในการส่งรัฐจากแอพแม่ลงสู่เส้นทาง ฉันได้โค้ดข้างต้นทำงานได้ แต่มันไม่ชัดเจนดังนั้นเมเจคที่ซ่อนอยู่นั้นน่าเกลียดไม่ใช่เรื่องง่ายที่จะติดตามและติดตามสิ่งที่เกิดขึ้น
Giant Elk

2
คำอธิบายประกอบการแพร่กระจาย มันไม่ชัดเจน แต่ไม่ใช่สิ่งที่แย่ที่สุดเนื่องจากคุณผ่านอุปกรณ์ประกอบฉากที่ไม่เปลี่ยนรูป
Meistro

นี่คือเอกสาร ReactJS ของผู้ดำเนินการเผยแพร่: facebook.github.io/react/docs/jsx-spread.htmlและfacebook.github.io/react/docs/transferring-props.html
Giant Elk

สิ่งนี้ใช้ได้สำหรับฉัน แต่ไวยากรณ์ที่ถูกต้องคือ {... this.props}
ชนะ

10

ใน 1.0 และ 2.0 คุณสามารถใช้createElementprop ของRouterเพื่อระบุวิธีการสร้างองค์ประกอบเป้าหมายของคุณ แหล่งเอกสาร

function createWithDefaultProps(Component, props) {
    return <Component {...props} myprop="value" />;
}

// and then    
<Router createElement={createWithDefaultProps}>
    ...
</Router>

6

นอกจากนี้คุณยังสามารถรวมฟังก์ชั่น 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
      }
    ]
}

ฉันไม่แน่ใจว่ามันทำงานอย่างไร - แต่มันดูผิด คุณกำลังใช้this.propsงานฟังก์ชั่นซึ่งฉันค่อนข้างมั่นใจว่าจะไม่ทำงาน หากคุณใช้งานฟังก์ชั่นแท้ๆแทนที่จะขยายออกไปReact.Componentคุณต้องผ่านpropsการโต้แย้งให้ดูที่ React docs บนComponents และ Props
icc97

6

React Router v 4 solution

วันนี้ฉันสะดุดกับคำถามนี้และนี่คือรูปแบบที่ฉันใช้ หวังว่านี่จะเป็นประโยชน์กับทุกคนที่กำลังมองหาทางออกที่เป็นปัจจุบันมากกว่านี้

ฉันไม่แน่ใจว่านี่เป็นทางออกที่ดีที่สุดหรือไม่ แต่นี่เป็นรูปแบบปัจจุบันของฉันสำหรับสิ่งนี้ ฉันมักจะมีไดเรกทอรีหลักที่ฉันเก็บส่วนประกอบที่ใช้กันทั่วไปของฉันด้วยการกำหนดค่าที่เกี่ยวข้องของพวกเขา (loader, modals, ฯลฯ ) และฉันรวมไฟล์ดังนี้:

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 () ตรวจสอบที่ตั้ง ฯลฯ

หวังว่านี่จะช่วยได้!


4

สำหรับการตอบสนองเราเตอร์ 2.x

const WrappedComponent = (Container, propsToPass, { children }) => <Container {...propsToPass}>{children}</Container>;

และในเส้นทางของคุณ ...

<Route path="/" component={WrappedComponent.bind(null, LayoutContainer, { someProp })}>
</Route>

ตรวจสอบให้แน่ใจพระราม 3 { checked: false }เป็นวัตถุที่ต้องการ:


1

ปัญหาของ 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();

1

ใช้ส่วนประกอบที่มีหรือไม่มีเราเตอร์ตามคำตอบของ 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>
};

0

สำหรับ 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'})}
  )
}
...

0

การใช้องค์ประกอบเส้นทางที่กำหนดเองสามารถทำได้ใน 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>โค้ดส่วนประกอบมันควรจะมีลักษณะดังนี้:

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


0

นี่อาจเป็นวิธีที่ดีที่สุดในการใช้ react-router-dom กับตัวจัดการคุกกี้

ใน 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}))
       }
      />
    )
}

0
class App extends Component {
  constructor(props){
    super(props);

    this.state = {
      data:null
    }


  }
 componentDidMount(){
   database.ref().on('value', (snapshot) =>{
     this.setState({
       data : snapshot.val()
      })
   });
 }

  render(){
  //  const { data } = this.state
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path = "/" component = { LandingPage }  />
        <Route 
          path='/signup' 
          render = { () => <Signup  data = {this.state.data} />} />
        </Switch>
    </BrowserRouter>

  );
  }
};

export default App;

0

ใช้วิธีแก้ปัญหาข้างต้นและใช้งานได้ใน v3.2.5

<Route
  path="/foo"
  component={() => (
    <Content
      lang="foo"
      meta={{
        description: lang_foo.description
      }}
    />
  )}
/>

หรือ

<Route path="/foo">
  <Content
    lang="foo"
    meta={{
      description: lang_foo.description
    }}
  />
</Route>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.