I have a module in react project and want to use nested routes with params in the middle of url, but after clicking the link it redirects to not found page.
The current page url like this:
"/AssetContext/Transfers/123"
And the nested route on the same page is like this:
"/AssetContext/Transfers/123/NewTransferItem"
My module is like this:
import React, { Component, Suspense } from "react";
import TransferDetails from "./transfer-details";
import { Link, Route, Switch } from "react-router-dom";
const Test = React.lazy(() => import("./test"));
const TransferItems = React.lazy(() => import("./transfer-items"));
const NewTransferItem = React.lazy(() => import("./new-transfer-item"));
class TransferItemsContainer extends Component {
state = {
transferId: this.props.match.params.id
};
render() {
const { transferId } = this.state;
return (
<>
<TransferDetails transferId={transferId} />
<Link to={`/AssetContext/Transfers/${transferId}/test`}>test</Link>
<Link to={`/AssetContext/Transfers/${transferId}/TransferItems`}>Transfer Items</Link>
<Link to={`/AssetContext/Transfers/${transferId}/NewTransferItem`}>New Transfer Items</Link>
<Switch>
<Route
exact
path={`/AssetContext/Transfers/:transferId/test`}
component={Test}
/>
<Route
path="/AssetContext/Transfers/:transferId/TransferItems"
render={() => <TransferItems transferId={transferId} />}
/>
<Route
path="/AssetContext/Transfers/:transferId/NewTransferItem"
render={() => <NewTransferItem transferId={transferId} />}
/>
</Switch>
</>
);
}
}
export default TransferItemsContainer;
But the routes don't hit!
what is the problem?!
Related
How do I pass the id from /profile/:id to the function generateProfile(findProfile(id))
Below is my code
import { Routes, Route } from 'react-router-dom';
import Profile from './Profile';
import '../assets/styles/App.css';
import seedProfiles from '../seedProfiles';
import generateProfile from '../helpers/profileHelper';
function App() {
const findProfile = id => seedProfiles.find(profile => profile.id === id);
return (
<Routes>
<Route exact="true" path="/" element={<h1>PROFILES</h1>} />
<Route
exact="true"
path="/profile/:id"
element={<Profile profile={generateProfile(findProfile(???))} />}
/>
</Routes>
);
}
export default App;
Thanks
Route path parameters are only accessible via the useParams hook. If you need to access the route path parameters prior to rendering the routed component then you'd need to create a wrapping component that can "sniff" the parameters and apply any logic.
Example:
const ProfileWrapper = ({ getProfile }) => {
const { id } = useParams();
return <Profile profile={getProfile(id)} />
};
function App() {
const getProfile = id => generateProfile(
seedProfiles.find(profile => profile.id === id)
);
return (
<Routes>
<Route path="/" element={<h1>PROFILES</h1>} />
<Route
path="/profile/:id"
element={<ProfileWrapper profile={getProfile} />}
/>
</Routes>
);
}
However, it's more common to move this logic into the component being rendered since there are not really any parental dependencies.
Example:
import { Routes, Route } from 'react-router-dom';
import Profile from './Profile';
import '../assets/styles/App.css';
import seedProfiles from '../seedProfiles';
import generateProfile from '../helpers/profileHelper';
const Profile = () => {
const { id } = useParams();
const profile = generateProfile(seedProfiles.find(profile => profile.id === id));
return ...;
}
import { Routes, Route } from 'react-router-dom';
import Profile from './Profile';
import '../assets/styles/App.css';
function App() {
return (
<Routes>
<Route path="/" element={<h1>PROFILES</h1>} />
<Route path="/profile/:id" element={<Profile />} />
</Routes>
);
}
I have the following problem: I have a general component that contains some data from the redux store and I want to clear this data once the user visits another route.
<Route path="/create/gallery" element={<CreatePage type={ContentType.gallery}/>} />
also I have some more code that saves my entered data to the store
saveGeneralInfo = (field: string, value: string) => {
const data = {};
data[field] = value;
this.props.dispatch(saveGeneralInfo(data));
}
How I can clear the state if the user leave the page or visit any other link? (For example from header)
if(this.state.keycloak) {
if(this.state.authenticated) return (
<div className="App">
<Header/>
<Routes>
<Route path="/" element={<Content />} />
<Route path="/sites"/>
<Route path="/users"/>
<Route path="/create/gallery" element={<CreatePage type={ContentType.gallery}/>}/>
<Route path="/create/article" element={<CreatePage type={ContentType.article} />} />
<Route path="/create/quiz" element={<CreatePage type={ContentType.quiz} />} />
</Routes>
</div>
);
else return (
<div>Can't authorize</div>
)
}
You will have to provide functionality for store clearing that fires on unMount lifecycle event in every route root component.
If you are using functional components:
export const Component = () => {
const dispatch = useDispatch();
useEffect(() => {
return () => {
dispatch(yourActionThatCleansReduxStore())
}
}, [])
//rest of your code
}
In my case I reset parts of my store for every page URL like /info or /user where store looks like
{
user: {
id: ...
},
info: ...
}
You can create a route controller using children component
import { useDispatch } from "react-redux";
import { useLocation } from "react-router-dom";
import { cleanState } from "Your-reducer.js";
function CleanState({ children }) {
const location = useLocation();
const dispatch = useDispatch();
useEffect(() => {
dispatch(cleanState()); // every time the route changes clean the state
// if you don't use redux-toolkit you can use action.payload etc....
},[location.pathname])
return <>{children}</>;
}
export default CleanState;
then you have to wrap the main component
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import YourComponents from "./YourComponents"; // Your components
import CleanState from "./CleanState"; // where did you save it
function App() {
return (
<Router>
<CleanState> // This is the previous component, this will listen the movements of the routes
<Routes>
<Route path="/main" element={<YourComponents />} />
<Route path="*" element={<YourComponents />} />
</Routes>
</CleanState>
</Router>
);
}
export default App;
I am creating a login in using react on the client and node on the server. From node I make the routes visible to the client, they are used with react router dom. This is my configuration of react router dom:
// React
import { Component, Fragment, Suspense, lazy } from "react";
// Components
import { Loading } from "./Loading";
// Librarys
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
// Layout
const Header = lazy(() => import("./Header"));
const Footer = lazy(() => import("./Footer"));
const PageNotFound = lazy(() => import("./PageNotFound"));
// Pages
const Home = lazy(() => import("./Home"));
const Products = lazy(() =>
import("./Products")
);
const Product = lazy(() =>
import("./Product")
);
// User Pages
const Login = lazy(() => import("./Login"));
const Register = lazy(() => import("./Register"));
class App extends Component {
render() {
return (
<Suspense
fallback={
<Loading />
}
>
<Router>
<Switch>
<Page path="/" component={Home} />
<Page path="/products" component={Products} />
<Page path="/products/:product" component={Product} />
<Page path="/contact" component={Contact} />
<Page path="/admin?login=true" component={Login} />
<Page path="/admin?register=true" component={Register} />
<Route
exact
path="/page-not-found"
component={PageNotFound}
/>
<Redirect to="/page-not-found" />
</Switch>
</Router>
</Suspense>
);
}
}
export default App;
class Page extends Component {
static defaultProps = {
exact: true,
sensitive: true
};
render() {
return (
<Fragment>
<Header />
<Route {...this.props} exact sensitive />
<Footer />
</Fragment>
);
}
}
My problem is in the "Login" and "Register" paths. They have added: "?login=true" and "?register=true". When entering any of those paths it shows me the 404 page. How to solve this? Use routes with parameters.
I'm wondering how I can direct the user to the correct language path for their location upon loading the page in react?
I know I can detect their locaalized langauge with navigator.language. But then how do I use that to route them to a page immediately?
You could have a functional component as a intro component in your app that will read that location and route to the correct language using the useHistory hook like this:
import { useHistory } from "react-router-dom";
function HomePage() {
const history = useHistory();
React.useEffect(() => {
// Use navigator.language here
history.push("/en");
}, []);
return (
<div>
Loading...
</div>
);
}
You can always read more about it in the React Router docs and in the React Hooks docs.
You should read https://reactrouter.com/web/api/
navigator.language returns the browser's language,
and I assume that it is what you really want
I did it with basename that is one of BrowserRouter properties
import {
BrowserRouter,
NavLink,
Redirect,
Route,
Switch
} from "react-router-dom";
import "./styles.css";
export default function App() {
const lang = navigator.language.split("-")[0];
return (
<div className="App">
<BrowserRouter basename={lang}>
<Menu />
<Switch>
<Redirect exact from="/" to="/home" />
<Route path="/" exact component={Home} />
<Route path="/home" exact component={Home} />
<Route path="/about" exact component={About} />
<Redirect to="/home" />
</Switch>
</BrowserRouter>
</div>
);
}
export const Menu = () => {
return (
<>
<NavLink to="./home">Home</NavLink>
<span> / </span>
<NavLink to="./about">About</NavLink>
</>
);
};
export const Home = () => {
return <h1>Home</h1>;
};
export const About = () => {
return <h1>About</h1>;
};
The App can't switch and render All the routes. It gets only one path (firstOne) and renders it.
import React, { Component } from "react";
import { Route, Switch } from "react-router-dom";
import { connect } from "react-redux";
class Board extends Component {
state = {
routes: []
};
showRoutes = routes =>
routes.length > 0 &&
routes.map((route, i) => (
<Route key={i} path={route.path} component={()=>"path"+i} />
));
render() {
const { routes } = this.props;
return (
<div>
<Switch>
<Route exact path="/" render={() => "start page"} />
{this.showRoutes(routes.routesApi)}
<Route path="/" render={() => "no such routes"} />
</Switch>
</div>
);
}
}
const mapStateToProps = state => ({
routes: state.routes
});
export default connect(mapStateToProps)(Board);
I have also used componentWillReceiveProps() as:
componentWillReceiveProps(NextProps) {
this.setState({ routes: NextProps.routes });
}
and switch to read data from state, but the result is the same.
Could you help me please to understand what is wrong?