2016-05-16 133 views
3

Here's an example from the docs.陣營路由器服務器服務器渲染道具

import { renderToString } from 'react-dom/server' 
import { match, RouterContext } from 'react-router' 
import routes from './routes' 

serve((req, res) => { 
    // Note that req.url here should be the full URL path from 
    // the original request, including the query string. 
    match({ routes, location: req.url }, (error, redirectLocation, renderProps) => { 
    if (error) { 
     res.status(500).send(error.message) 
    } else if (redirectLocation) { 
     res.redirect(302, redirectLocation.pathname + redirectLocation.search) 
    } else if (renderProps) { 
     // You can also check renderProps.components or renderProps.routes for 
     // your "not found" component or route respectively, and send a 404 as 
     // below, if you're using a catch-all route. 
     res.status(200).send(renderToString(<RouterContext {...renderProps} />)) 
    } else { 
     res.status(404).send('Not found') 
    } 
    }) 
}) 

我有一個這樣的對象:

let reactServerProps = { 
    'gaKey': process.env.GA_KEY, 
    'query': req.query, 
} 

我想這個對象傳遞到反應路由器這裏

res.status(200).send(renderToString(<RouterContext {...renderProps} {...reactServerProps} />)) 

我似乎無法提供對組件內部變量的訪問。

回答

3

問題是,<ReactContext />僅將一些反應路由器預定義的道具傳遞給它構建的組件樹,而不是您在常規組件中可能需要的自定義道具。

這個問題有幾個解決方法,雖然他們都不是特別漂亮。我認爲我見過的使用最廣泛的是將<ReactContext />包裝爲一個組件,其唯一目的是利用React的上下文功能&將上下文數據傳遞給其子項而不是道具。

所以:

import React from 'react'; 

export default class DataWrapper extends React.Component { 

getChildContext() { 

    return { 
     data: this.props.data 
    }; 

} 

render() { 

    return this.props.children; 
} 
} 
在您的Express服務器

然後:

// Grab the data from wherever you need then pass it to your <DataWrapper /> as a prop 
// which in turn will pass it down to all it's children through context 
res.status(200).send(renderToString(<DataWrapper data={data}><RouterContext {...renderProps} /></DataWrapper>)) 

然後你應該能夠訪問這些數據在您的子組件:

export default class SomeChildComponent extends React.Component { 

constructor (props, context) { 

    super(props, context); 
    this.state = { 
     gaKey: context.data.gaKey, 
     query: context.data.query 
    }; 
} 

}; 

我知道它曾經有可能利用createElement方法來設置一些自定義道具並傳遞給它們以類似的方式給你的孩子的路線,但我並不積極,在更新版本的react-router中仍然有效。請參閱:https://github.com/reactjs/react-router/issues/1369


UPDATE:它仍然可以使用中間件傳遞額外的值到線路零部件。通過:https://github.com/reactjs/react-router/issues/3183

,你應該能夠利用道具超過背景:

function createElementFn(serverProps) { 
    return function(Component, props) { 
    return <Component {...serverProps} {...props} /> 
    } 
} 

然後在你的<RouterContext />添加createElement像這樣,通過它您serverProps:

res.status(200).send(renderToString(<RouterContext {...renderProps} createElement={createElementFn(serverProps)} />)) 

,並獲得他們在任何你的孩子的組件中都有一個簡單的this.props.gaKey & this.props.query

+0

我已經使用'props'命名空間尋找變量來連接所有組件。有什麼方法可以將數據作爲「道具」傳遞嗎? – ThomasReggi

+0

您可以在createElement方法中使用裂縫,我在這裏找到了一個實現:http://stackoverflow.com/questions/33978781。儘管如此,自從react-router v1以來,我並不樂觀。 我認爲使用Object'assign()'方法將數據直接注入到'renderProps'中也是可能的,儘管它感覺很不方便。即分配(renderProps.params,reactServerProps)' –

+0

@ThomasReggi好消息,似乎將價值作爲道具傳遞給所有孩子而非上下文仍然是完全可行的。更新瞭解釋的答案。 –

-1

一個更簡單的方法是把你想要的任何數據props.routes,它會被傳遞給你的組件,你可以通過

props.routes.[whatever you passed in]

所以在服務功能直接訪問它,你可以做

props.routes.reactServerProps = { 
'gaKey': process.env.GA_KEY, 
'query': req.query 
} 

並且在您的組件中,您可以使用props.routes.reactServerProps訪問它。

查看Ryan Florence的最新評論。 https://github.com/ReactTraining/react-router/issues/1017

他忘了(s)。不會與路線一起工作。