At first the question seems easy but it took me quite long to figure out how to do this! This is the only way I can think of right now. If there's some suggestions on how to improve the codes, feel free to submit a change request :)
I cannot guarantee that this is the best way of doing this, but it works for your case.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import {
BrowserRouter as Router,
Route,
Switch,
NavLink,
useRouteMatch,
Redirect
} from "react-router-dom";
import "./styles.css";
const datasetWithVersions = {
id: "dataset-with-versions",
versions: 2,
versionList: [
{
version: 1,
size: 20001
},
{
version: 2,
size: 191232
}
],
name: "a-dataset-with-2-versions"
};
const datasetWithNoVerrsions = {
id: "dataset-with-no-versions",
versions: 0,
name: "an-empty-dataset"
};
function loadDataset() {
return new Promise(resolve => {
setTimeout(() => {
if (Math.random() >= 0.5) {
console.log("loading dataset with versions....");
resolve(datasetWithVersions);
} else {
console.log("loading dataset with no versions....");
resolve(datasetWithNoVerrsions);
}
}, 1000);
});
}
function App() {
return (
<div className="App">
<Router>
<Switch>
<Route path="/dataset" component={DatassetComponent} />
<Redirect to="/dataset" />
</Switch>
</Router>
</div>
);
}
function DatassetComponent() {
let [dataset, setDataset] = useState(null);
const match = useRouteMatch();
useEffect(() => {
loadDataset().then(data => setDataset(data));
}, []);
if (!dataset) return <div>loading...</div>;
const getURL = to => {
if (dataset.versions) {
return `${match.path}/${dataset.versions}/${to}`;
}
return `${match.path}/${to}`;
};
return (
<div>
<div className="navbar">
<NavLink to={getURL("overview")} activeClassName="active">
OverView
</NavLink>
{dataset.versions ? (
<NavLink to={getURL("versions")} activeClassName="active">
Versions
</NavLink>
) : null}
<NavLink to={getURL("settings")} activeClassName="active">
Settings
</NavLink>
</div>
<div className="content">
<Switch>
<Route path={getURL("versions")}>
<div>Versions</div>
</Route>
<Route path={getURL("settings")}>
<div>settings</div>
</Route>
<Route path={getURL("overview")}>
<div>Overview for dataset {dataset.name}</div>
</Route>
<Redirect to={getURL("overview")} />
</Switch>
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Working code sandbox: https://codesandbox.io/s/react-router-optional-path-demo-p50b4?fontsize=14