2016-10-10 10 views
0

Lassen Sie uns sagen, ich habe eine Foo Komponente mit einigen Router Reagieren Navigation:Erweiterung Komponenten mit React Router

var Foo = React.createClass({ 
    render: function() { 
     return (<div> 
      <Link to="/foo/1">1</Link>; 
      <Link to="/foo/2">2</Link>; 
      {this.props.children} 
     </div>); 
    } 
}); 
var Foo1 = React.createClass({ 
    render: function() { 
     return <p>foo 1</p>; 
    } 
}); 
var Foo2 = React.createClass({ 
    render: function() { 
     return <p>foo 2</p>; 
    } 
}); 
ReactDOM.render((
    <Router> 
     <Route path="/" ...> 
      <Route path="foo" component={Foo}> 
       <Route path="1" component={Foo1} /> 
       <Route path="2" component={Foo2} /> 
      </Route> 
     </Route> 
    </Router> 
), document.getElementById('main')); 

Lassen Sie uns jetzt sagen, dass ich auch eine Bar-Komponente haben, die sehr ähnlich ist (mit Ausnahme von, na ja, bar statt foo). In einer „klassischen“ React Anwendung, hätte ich „extrahiert“ die gemeinsame Logik aus, etwa so:

var Element = React.createClass({ 
    render: function() { 
     return (<div> 
      <Link to={this.props.url + '/1'}>1</Link>; 
      <Link to={this.props.url + '/2'}>2</Link>; 
      {this.props.children && React.cloneElement(this.props.children { 
       name: this.props.name // Ugly hack to propagate props... 
      })} 
     </div>); 
    } 
}); 
var Element1 = React.createClass({ 
    render: function() { 
     return <p>{this.props.name} 1</p>; 
    } 
}); 
var Element2 = React.createClass({ 
    render: function() { 
     return <p>{this.props.name} 2</p>; 
    } 
}); 
var Foo = React.createClass({ 
    render: function() { 
     return <Element url="/foo" name="foo" />; 
    } 
}); 
var Bar = React.createClass({ 
    render: function() { 
     return <Element url="/bar" name="bar" />; 
    } 
}); 

Wie Sie sehen können, habe ich fast es wurde (sogar, dass hässliche Ausbreitung Hack Requisiten. ..). Der Teil fehlt mir ist, wie das Routing zu definieren selbst:

ReactDOM.render((
    <Router> 
     <Route path="/" ...> 
      <Route path="foo" component={Foo}> 
       <Route path="1" component={?} /> 
       <Route path="2" component={?} /> 
      </Route> 
     </Route> 
    </Router> 
), document.getElementById('main')); 

ich meine, es gibt nicht mehr Foo1 und Foo2 Komponenten, weil Foo eine Element hat, aus dem sie allgemein abgeleitet werden. Ich könnte natürlich Foo1 explizit definieren, um eine Element1 und Foo2 zu haben, um eine Element2 zu haben, aber dann würde ich Foo implementieren müssen, anstatt die Element es für mich machen zu lassen; oder vielleicht könnte ich die Komponenten selbst als Requisiten übergeben (also Foo = ... <Element ... component1={Foo1} component2={Foo2} /> ... aber was dann?).

Also: wie kann ich diese reaktive "Vererbung über Komposition" mit React Router erreichen? Oder gibt es einen anderen Weg, das zu tun?

Antwort

0

Ich dachte an eine Lösung, also dachte ich, ich würde es für Leute mit einem ähnlichen Problem posten. Bitte beachten Sie, ich bin noch neu in diesem .. uh .. "Denkweise", also könnte es nicht der bestmögliche Weg sein.

Hier ist das Ding: Die foo/bar Differenz (url="/foo|/bar" und name="foo|bar") in einen einzigen "foo|bar"-Tag „zusammengefasst“ werden, die dann in die URL als Parameter extrahiert werden können. Das heißt:

ReactDOM.render((
    <Router> 
     <Route path="/" ...> 
      <Route path="/:tag" component={Element}> 
       <Route path="/:tag/1" component={Element1} /> 
       <Route path="/:tag/2" component={Element2} /> 
      </Route> 
     </Route> 
    </Router> 
), document.getElementById('main')); 

Und die Elemente neu geschrieben werden können, den Tag zu berücksichtigen:

var Element = React.createClass({ 
    render: function() { 
     return (<div> 
      <Link to={'/' + this.props.params.tag + '/1'}>1</Link>; 
      <Link to={'/' + this.props.params.tag + '/2'}>2</Link>; 
      {this.props.children} 
     </div>); 
    } 
}); 
var Element1 = React.createClass({ 
    render: function() { 
     return <p>{this.props.params.tag} 1</p>; 
    } 
}); 
var Element2 = React.createClass({ 
    render: function() { 
     return <p>{this.props.params.tag} 2</p>; 
    } 
}); 

Und das ist es! Sie benötigen nicht einmal die Komponenten <Foo /> und <Bar />.

Der Grund, warum ich nicht vollkommen glücklich über diese Lösung bin, ist, dass es für einen einfachen Fall funktioniert (wie dieses Beispiel oder das CMS, an dem ich gerade arbeite), aber ich bin mir nicht sicher, dass es auf mehr skaliert komplizierte Designs; das, und da ist der URL-Konflikt: eine /baz Route mit einer <Baz /> Komponente muss zuerst angezeigt werden, andernfalls würde <Element /> mit dem "baz"-Tag stattdessen ausgewertet werden. Ich habe immer noch nicht gefunden, wie man komplexe Parameter (wie reguläre Ausdrücke) mit React Router definiert, aber wenn ich das tue, werde ich die Antwort aktualisieren.

Verwandte Themen