2017-08-03 6 views
2

私はReact、React-Router(v5)とReduxでアプリケーションを構築しており、親ルートの現在の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)) 

問題はURLがhttp://localhost:3000/projects/14ですが、私のrender方法でconsole.log出力が{"path":"/projects","url":"/projects","isExact":false,"params":{}}であること、です。

私はProjectListID小道具を追加して、現在選択されているプロジェクトを強調したいと考えています。

私のProjectPageコンポーネント内の店舗にプロジェクトのIDを保存することができましたが、これはちょっと混乱していると思います。特にURLに実際に情報があるためです。

別の(悪い?)アプローチは、自分自身でIDを取得するロケーションオブジェクトを解析することですが、私が見落としたこの時点でパラメータを取得するにはreact-router/react-router-reduxの方法があると思います。

答えて

3

@カイルは技術的な観点から非常にうまく説明しています。 私はその問題の解決に焦点を合わせます。

matchPathを使用して、選択したプロジェクトのidを取得できます。

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

これは、サーバー上でレンダリングする前にデータ 依存関係を集めるように、通常のレンダリングサイクルの 外を除いて使用するのと同じマッチングコードを使用することができます。

この場合の使用法は非常に単純です。

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

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でのレンダリングは、私はあなたのプロジェクトで同じ機能を実装するために使用できる簡単なデモを構築します。

デモ:https://codesandbox.io/s/pQo6YMZop

私たちはまた、ルータのパスマッチングに使用される公式react-router APIを使用しているため、このソリューションは非常にエレガントだと思います。 window.locationもここでは使用しません。したがって、生のコンポーネントもエクスポートすると、テスト/模擬が簡単になります。

+0

これは素晴らしいです!それは私が探していたものです:-)現時点で私は 'router-parser'を使っていますが、' react-router'パッケージのメソッドを使うことは絶対的な意味を持ちます。実際には、私はすでにルートに定数を使用しています:-) – Slevin

1

TLDR

はあなた<Route />pathプロパティは:paramsが含まれていない場合、ルータmatch.paramsは空のオブジェクトになります反応します。

:親ルートのコンポーネントにlet id = window.location.pathname.split("/").pop();を使用してIDを取得できます。

詳細な理由はない

<Route />に供給path小道具は、/:idなどの任意のparamsを、持っていない場合は、ルータはあなたのための解析を行うには行っていない反応します。 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; 
    }, {}) 
}; 

その後、我々はkeys_compilePath.keysから来ていることをあなたが見ることができるライン#43を見ることができます。私たちは、その後、compilePath機能を見て、その後keys.push(token)とライン#355にkeysを変異されるtokensToRegExp()を使用するであろう、stringToRegexp()を使用するであろう、それはpathToRegexp()を使用していることがわかります。 path小包内にparams値を持たないを使用すると、stringToRegexp()で使用されるparse()関数はトークンを返さず、トークン配列だけにトークンオブジェクトが含まれないため、#355にも到達しません。

には:paramsがない場合、キーの値は空の配列になり、matchにはパラメータがありません。

結論として、あなたのルートがそれらを考慮していない場合は、あなた自身でパラメータを取得する必要があるように見えます。あなたはlet id = window.location.pathname.split("/").pop()を使ってそれにすることができます。

関連する問題