2015-11-06 6 views
5

Я не могу понять, как передать реквизиты компоненту. Это важно, поскольку я не хочу извлекать данные в методе componentDidMount, так как он будет невидимым для поисковых систем.С getComponent как пройти реквизит?

Мой код выглядит следующим образом

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> 

Я пытаюсь обслуживать портфель React приложения, когда пользователь посещает действительный URL как mysite.com/thishandleisvalid, но мне нужно также извлечь все содержимое для этого приложения на отметке getComponent и передать его как собственность. Например. вы обычно можете сделать что-то вроде этого <Portfolio contentItems={fetchedItems} />.

Делает это возможно?

ответ

16

Это действительно легко сделать с компонентами без гражданства. Просто сделать что-то вроде:

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

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

Причина мы явно не поддерживают такого рода шаблон, потому что это довольно нетипичный телеграфировать вещи таким образом - для приложений, которые должны иметь дело с такого рода вещи, это много более общий для использования крюка onEnter, например, заполнить хранилище Flux, а затем подключить компоненты, соответствующие соответствующим хранилищам.

+0

Это великолепно работает. И спасибо за информацию об использовании крюка onEnter и хранилища флюсов. Это все еще область, которую я нахожу в замешательстве и нуждаюсь в изучении. – Ally

+0

Это хорошо работает для меня, поскольку я пытаюсь передать действия только компоненту на основе маршрута, не загрязняя реквизит в приложении, скажем, если бы я использовал «React.cloneElement (this.props.children, {'действия ': fooActions})' в корне приложения. – mpoplin

5

Кроме того, если вы не возражаете доступа реквизита под route, вы можете передать реквизит, как это:

JSX:

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

Programatically:

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

И customProp будет доступен через props.route.customProp

+1

Имеется документация об этом? –

0

карринг выглядит более простым способом (и даже более проще с Перекомпонуйте/withProps)

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

UPDATE

ВНИМАНИЕ: ИСПОЛНЕНИЯ моя версия просто обсахаривания над ответом taion, в и, я полагаю, имеет те же проблемы: он вызывает полное перераспределение компонента при перенаправлении.

Это происходит из-за перекомпоновки компонента с помощью усилителя forProps в каждом новом месте, который генерирует новый компонент при каждом перенаправлении.

В качестве быстрого решения я решил убрать все улучшения в слабых картах. в моем случае это выглядит как

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); 
} 
Смежные вопросы