2017-08-03 37 views
2

PARAMS我建設有反應的應用,做出反應,路由器(V5)和終極版,不知道如何訪問當前URL的PARAMS在父路徑。如何讓父路由組件

這是我的條目中,router.js

<Wrapper> 
    <Route exact path="/login" render={(props) => (
    <LoginPage {...props} entryPath={this.entryPath} /> 
)} /> 

    <Route exact path="/" component={UserIsAuthenticated(HomePage)} /> 
    <Route exact path="/about" component={UserIsAuthenticated(AboutPage)} /> 
    <Route path="/projects" component={UserIsAuthenticated(ProjectsPage)} /> 
</Wrapper> 

這就是我的ProjectsPage組件:

class ProjectsPage extends PureComponent { 
    componentDidMount() { 
    this.props.fetchProjectsRequest() 
    } 

    render() { 
    console.log(this.props.active) 

    if (this.props.loading) { 
     return <Loading /> 
    } else { 
     return (
     <Wrapper> 
      <Sidebar> 
      <ProjectList projects={this.props.projects} /> 
      </Sidebar> 
      <Content> 
      <Route exact path="/projects" component={ProjectsDashboard} /> 

      <Switch> 
       <Route exact path="/projects/new" component={ProjectNew} /> 
       <Route exact path="/projects/:id/edit" component={ProjectEdit} /> 
       <Route exact path="/projects/:id" component={ProjectPage} /> 
      </Switch> 
      </Content> 
     </Wrapper> 
    ) 
    } 
    } 
} 

const enhance = connect(
    (state, props) => ({ 
    active: props.match, 
    loading: projectSelectors.loading(state), 
    projects: projectSelectors.projects(state) 
    }), 
    { 
    fetchProjectsRequest 
    } 
) 

export default withRouter(enhance(ProjectsPage)) 

的問題是,在我的render方法console.log輸出爲{"path":"/projects","url":"/projects","isExact":false,"params":{}}雖然URL是http://localhost:3000/projects/14

我想添加一個ID道具到我的ProjectList以突出顯示當前選定的項目。

我可以將項目ID保存在我的ProjectPage組件中的商店中,但我認爲這會有點令人困惑,尤其是因爲URL實際上具有這些信息 - 所以爲什麼我應該在商店中寫些東西?

另一個(壞?)方法是解析位置對象並自己獲取ID,但我認爲有一個方法可以獲得我忽略的參數。

回答

3

@Kyle從技術角度解釋了問題。 我只會專注於解決這個問題。

您可以使用matchPath獲得所選項目的id

matchPath - https://reacttraining.com/react-router/web/api/matchPath

這可讓您使用使用相同的匹配代碼除了 超出正常的渲染週期,像渲染服務器之前收集了數據 依賴性。

在這種情況下的使用非常簡單。

1使用matchPath

// history is one of the props passed by react-router to component 
// @link https://reacttraining.com/react-router/web/api/history 

const match = matchPath(history.location.pathname, { 
    // You can share this string as a constant if you want 
    path: "/articles/:id" 
}); 

let articleId; 

// match can be null 
if (match && match.params.id) { 
    articleId = match.params.id; 
} 

2使用articleId在渲染

{articleId && (
    <h1>You selected article with id: {articleId}</h1> 
)} 

我建立一個簡單的演示,你可以用它來實現您的項目相同的功能。

演示:https://codesandbox.io/s/pQo6YMZop

我認爲,這個解決方案是很優雅的,因爲我們使用的官方react-router API,它也可用於路由器路徑匹配。我們在這裏也不使用window.location,因此如果您導出原始組件,測試/模擬也將變得非常簡單。

+0

這太棒了!這就是我所尋找的:-)目前我正在使用'router-parser',但是使用'react-router'包中的方法是絕對有意義的。事實上,我已經在使用路由的常量了:-) – Slevin

1

TLDR

陣營路由器match.params將是一個空的對象,如果你<Route />path屬性不包括:params

解決此使用案例:您可以在父路由的組件中使用let id = window.location.pathname.split("/").pop();以獲取該ID。

詳細理由不

如果提供給<Route />path道具沒有任何參數,可以如/:id,反應路由器是不會做解析爲您服務。如果您在matchPath.js在行#56看你就可以開始看到match道具是如何構建的。

return { 
    path: path, // the path pattern used to match 
    url: path === '/' && url === '' ? '/' : url, // the matched portion of the URL 
    isExact: isExact, // whether or not we matched exactly 
    params: keys.reduce(function (memo, key, index) { 
     memo[key.name] = values[index]; 
     return memo; 
    }, {}) 
}; 

然後,我們可以看一下線#43你可以看到,keys來自_compilePath.keys。然後我們可以看看compilePath函數,並看到它使用pathToRegexp(),它將使用stringToRegexp(),它將使用tokensToRegExp(),然後它將在#355號線上與keys.push(token)變異keys。隨着<Route />,在其path道具沒有PARAMS價值,stringToRegexp()使用parse()功能將不返回355甚至不會達成任何標記和線#因爲只有令牌陣列將不包含任何令牌對象。

因此....如果您的<Route />沒有:params那麼鍵值將是一個空數組,您將不會在match上有任何參數。

總之,如果你的路線沒有考慮到它,你會得到自己的參數。你可以通過使用let id = window.location.pathname.split("/").pop()

相關問題