Brack
Brack

Reputation: 333

React: How to get variable from URL?

I'm building an application that needs to load a "workspace" from the database based on the slug provided in the URL. My URL structure is /app/<workspace slug>/<workspace view>. Currently there are 3 views for each workspace: Map, List and Settings. I need to get the value of the <workspace slug> from the URL in order to load the correct workspace from the database. Also I need to return an error if the workspace is not found.

I'm pretty new to React so I may not currently be following best practices.

My Routing

Currently I'm routing to each workspace view by looping through each workspace and creating a route for each of the 3 views in App.js:

renderContent() {
    return (
        <Switch>
            <Route path="/" component={NetworkMap} exact />
              {this.state.workspaces.map(function(workspace, index){ // Map View Routes
                return (
                  <Route path={"/app/" + workspace.slug + "/map"} render={(props) => <Workspace {...props} workspace={workspace} component={Map} />} />
                );
              })}
              {this.state.workspaces.map(function(workspace, index){ // List View Routes
                return (
                  <Route path={"/app/" + workspace.slug + "/list"} render={(props) => <Workspace {...props} workspace={workspace} component={List} />} />
                );
              })}
              {this.state.workspaces.map(function(workspace, index){ // Settings View Routes
                return (
                  <Route path={"/app/" + workspace.slug + "/settings"} render={(props) => <Workspace {...props} workspace={workspace} component={WorkspaceSettings} />} />
                );
              })}
            <Route component={Error} />
        </Switch>
    );
}

My Links

{props.workspaces.map(function(workspace, index){
  return (<Link key={index} to={"/app/" + workspace.slug + "/map"} className="dropdown-item cursor-pointer">{workspace.name}</Link>);
})}

My Index.js

<BrowserRouter>
    <App />
</BrowserRouter>

I've tried changing workspace.slug to :slug in the Route's path which I thought should make it appear in props but I can't seem to get it working properly:

{this.state.workspaces.map(function(workspace, index){
  return (
    <Route path={"/app/:slug/map"} render={(props) => <Workspace {...props} workspace={workspace} component={Map} />} />
  );
})}

Upvotes: 0

Views: 797

Answers (1)

Drew Reese
Drew Reese

Reputation: 202658

match

Components rendered via the render prop will also be passed some route props, specifically, match is the one you want. From there props.match.params.slug will be the slug value you want

{this.state.workspaces.map(function(workspace, index){
  return (
    <Route
      path="/app/:slug/map"
      render={props => (
        <Workspace
          {...props}
          workspace={workspace}
          component={Map}
          slug={props.match.params.slug}
        />
      )}
    />
  );
})}

match can also be access within the component Workspace via the spread in props. If Workspace is a functional component, react-router-dom also has a useParams hook.

Upvotes: 1

Related Questions