2015-11-06 10 views
5

Nie mogę wymyślić, jak przekazać rekwizyty do komponentu. Jest to ważne, ponieważ nie chcę pobierać danych w metodzie componentDidMount, ponieważ będzie to niewidoczne dla wyszukiwarek.Z getComponent jak przekazywać rekwizyty?

Mój kod wygląda następująco

const router = 
<Route path="/" component={App}> 
<IndexRoute onEnter={redirectToLogin} component={LandingPage} /> 
<Route path="panel" component={ ControlPanel }> 
    ... 
</Route> 
<Route 
    path="/:handle" 
    onEnter={maybeRedirectToHome} 
    getComponent={(location, callback)=> { 
     getSiteHandleByName(location.pathname.slice(1)) 
     .then(function(handle){ 
     if (handle){ 
      callback(null, Portfolio) 
     } else { 
      callback(null, NotFound) 
     } 
     }) 
     .catch(callback) 
    }} 
    getChildRoutes={(location, callback)=> { 
    callback(null, portfolioRoutes) 
    }} 
/> 
</Route> 

Próbuję służyć do portfela React aplikacji, gdy użytkownik odwiedza prawidłowy adres URL jak mysite.com/thishandleisvalid ale Muszę również pobrać całą zawartość dla tej aplikacji w punkcie getComponent i przekazuj go jako właściwość. Na przykład. możesz normalnie zrobić coś takiego: <Portfolio contentItems={fetchedItems} />.

Czy to jest możliwe?

Odpowiedz

16

Jest to bardzo proste w obsłudze dzięki elementom bezpaństwowym. Wystarczy zrobić coś takiego:

function getComponent(location, callback) { 
    const Component = /* ... */; 
    const items = /* ... */; 

    callback(null, props => <Component {...props} items={items} />); 
} 

powód, dla którego wyraźnie nie obsługuje tego rodzaju wzór, ponieważ jest to dość nietypowy drut rzeczy w ten sposób - w przypadku aplikacji, które muszą radzić sobie z tego typu rzeczy, to znacznie bardziej powszechne użycie haka onEnter do np zapełnij magazyn Flux, a następnie podłącz komponenty odpowiednio do odpowiednich sklepów.

+0

To działa wielkie dzięki. I dziękuję za informacje na temat używania haka onEnter i magazynu flux. To wciąż obszar, który uznaję za mylący i muszę się czegoś dowiedzieć. – Ally

+0

Działa to dobrze dla mnie, ponieważ próbuję tylko przekazywać działania do komponentu na podstawie trasy bez zanieczyszczania rekwizytów w całej aplikacji, na przykład, jeśli użyłem "React.cloneElement (this.props.children, {'actions ": fooActions})" w katalogu głównym aplikacji. – mpoplin

5

Także, jeśli nie przeszkadza dostępu rekwizytów pod route, można przekazać rekwizyty tak:

JSX:

<Route 
    path="route_path" 
    customProp="hello" 
    getComponent={(location, cb) => { 
    // ... 
    }} 

Programowo:

childRoutes: [ 
{ 
    path: 'route_path', 
    customProps: 'hello', 
    getComponent(location, cb) { 
    // .... 
    }, 

I customProp będzie dostępny pod numerem props.route.customProp

+1

Istnieje pewna dokumentacja na ten temat? –

0

Zmiękczanie wygląda jak prostszy sposób (a nawet bardziej prostsze z recompose/withProps)

const getComponentWithProps = (props) => 
    (location, cb) => { 
    const Component = /* ... */; 
    // ... 
    cb(null, withProps(props)(Component)) 
    } 
... 
childRoutes: [ 
    { 
    path: 'route_path', 
    getComponent: getComponentWithProps({ foo: 'bar' }), 
    } 
] 

UPDATE

UWAGA: PERFORMANCE moja wersja jest tylko dosładzanie nad odpowiedzią Taion za, i, jak przypuszczam, ma te same problemy: powoduje całkowite zrestartowanie komponentu podczas zmiany trasy.

dzieje się tak z powodu przepinania komponentu ze wzmacniaczem withProps w każdej nowej lokalizacji, która generuje nowy komponent przy każdej zmianie trasy.

jako szybkie rozwiązanie postanowiłem buforować wszystkie ulepszenia w mapach słabych. w moim przypadku wygląda to na:

const getOrAdd = (map) => 
    (value = Function.prototype) => 
    (key) => 
     map.get(key) 
     || (
      map.set(
      key, 
      value(), 
     ) 
      && map.get(key) 
     ); 

const componentsMap = new WeakMap(); 
export const getEnhancedMap = getOrAdd(componentsMap)(() => new WeakMap()); 

export const getEnhancedComponent = (
    component, 
    enhancer, 
) => { 
    const enhancedMap = getEnhancedMap(component); 
    return getOrAdd(enhancedMap)(() => enhancer(component))(enhancer); 
} 
Powiązane problemy