I have two types of routes, countries and content:
/countries
/industry/ranking
/industry/audience
/website/ranking
/website/audience
/website/conversion
etc...
When the user enters the application, I have to verify if he already chose a country, which I'm saving using localStorage.
If the user has the country already chosen, he needs to go to /industry/ranking, if don't, to /countries.
I'm receiving a warning about the route changing by code:
<Route> elements should not change from controlled to uncontrolled (or vice versa). You provided a "location" prop initially but omitted it on a subsequent render.
My code:
<Switch>
<Route exact path='/countries' component={Countries} />
{
current && (
<React.Fragment>
<Route exact path='/industry/ranking' render={() => <IndustryRanking country={current} />} />
<Route path='/industry/audience' render={() => <IndustryAudience country={current} />} />
<Route path='/website/ranking' render={() => <WebsiteRanking country={current} />} />
<Route path='/website/audience' render={() => <WebsiteAudience country={current} />} />
<Route path='/website/device' render={() => <WebsiteDevice country={current} />} />
<Route path='/website/conversion-orders' render={() => <WebsiteConversionOrders country={current} />} />
</React.Fragment>
)
}
{ !current ? <Redirect to='/countries' /> : <Redirect to='/industry/ranking' /> }
</Switch>
Is there a way to improve this using just the routes to verify my condition?
Thanks!
You can simply write a custom component that renders the Routes or redirects to the country instead of conditionally rendering the Routes which is causing this warning
const CustomRoute = (props) => {
const current = localStorage.getItem('country');
if(current) {
return <Route {...props} />
}
return <Redirect to='/countries' />
}
and use it like
<Switch>
<CustomRoute exact path='/countries' component={Countries} />
<CustomRoute exact path='/industry/ranking' render={() => <IndustryRanking country={current} />} />
<CustomRoute path='/industry/audience' render={() => <IndustryAudience country={current} />} />
<CustomRoute path='/website/ranking' render={() => <WebsiteRanking country={current} />} />
<CustomRoute path='/website/audience' render={() => <WebsiteAudience country={current} />} />
<CustomRoute path='/website/device' render={() => <WebsiteDevice country={current} />} />
<CustomRoute path='/website/conversion-orders' render={() => <WebsiteConversionOrders country={current} />} />
<Redirect to='/industry/ranking' />
</Switch>
Related
I'm developing react app use react-router-dom. I have unusual the app behavior. The app doesn't have home page. We can go to the app use 'slug'. For example: http://siteExample.net/my-subsite. If my-subsite exist in our database We need to work with this slug.
My code snippet for routes:
const App = ({ isAuth, onSetSlug, slug}) => {
useEffect(() => {
onSetSlug(window.location.pathname.split('/')[1])
}, [])
return (
<Router>
<div className="App">
<Suspense fallback={<Loading />}>
<MainModal />
<ScrollToTop>
{!isAuth ? (
<Switch>
<Route path={'/:slug'} exact component={lazy(() => import('./containers/notAuth/home'))} />
<ContentWrapper
container
component="main"
adaptSidebar={5}
adaptContent={7}
>
<Switch>
<Route path={'/:slug/login'} exact component={lazy( () => import('./containers/notAuth/login'))} />
<Route path={'/:slug/signup'} exact component={lazy(() => import('./containers/notAuth/signup'))} />
<Redirect to={'/:slug'} />
</Switch>
</ContentWrapper>
<Redirect to={'/:slug'} />
</Switch>
</ScrollToTop>
</Suspense>
</div>
</Router>
)}
There is a issue that :slug/login doesn't replace on my-subsite/login for example.By the way it's working only for my local machine. When I publish it to remote host it doesn't work completely.
Remove the exact prop on the outer/root route since it necessarily excludes matching any subroutes.
<Switch>
<Route
path={'/:slug'} // <-- want this path prefix to match
component={lazy(() => import('./containers/notAuth/home'))}
/>
<ContentWrapper
container
component="main"
adaptSidebar={5}
adaptContent={7}
>
<Switch>
<Route
path={'/:slug/login'}
exact
component={lazy( () => import('./containers/notAuth/login'))}
/>
<Route
path={'/:slug/signup'}
exact
component={lazy(() => import('./containers/notAuth/signup'))}
/>
<Redirect to={'/:slug'} />
</Switch>
</ContentWrapper>
<Redirect to={'/:slug'} />
</Switch>
I have built a UI amazon-clone with create-react-app
it only shows dummy data.
the problem is after publishing it to Vercel, the routing not working as expected! after clicking the links you see a blank page "URL params are correct", you have to manually reload the page to work!
also if you clicked a button no event trigger and you get a blank page!
I wrapped all my routes to MainRoute Component:
const MainRoute = withRouter(({ location }) => {
return (
<>
{location.pathname !== "/login" && location.pathname !== "/signup" ? (
<Header />
) : null}
<Switch>
<Route exact path="/" render={() => <Home />} />
<Route exact path="/products" render={() => <Products />} />
<Route
exact
path="/products/:productID"
render={() => <ProductPage />}
/>
<Route path="/checkout" render={() => <Checkout />} />
<Route path="/payment" render={() => <Payment />} />
<Route path="/login" render={() => <Login />} />
<Route path="/signup" render={() => <Signup />} />
<Route render={() => <NotFoundPage />} />
</Switch>
{location.pathname !== "/login" && location.pathname !== "/signup" ? (
<Footer />
) : null}
</>
);
});
export default withRouter(MainRoute);
my App Component:
function App() {
return (
<div className="app_wrapper">
<Router>
<MainRoute />
</Router>
</div>
);
}
export default App;
repo
https://github.com/aseelban/amazon-clone-app
link:
https://amazon-clone-app-llyl1tfcn.vercel.app/
it works correctly (under Brave browser) the authentication routes, could you please specify which route the issue occurs.!
Thanks, everyone for the help.
I solved this problem by removing HOC withStyles and instead use react-jss.
i wanted to iterate on the list of components as you can there is lot of redundancy so for example i have long list of routes just as given below
<Route
exact
path={Routes.HOME}
render={() => (
<LandingPage
setValue={setValue}
setSelectedIndex={setSelectedIndex}
/>
)}
/>
<Route
exact
path={Routes.SERVICES}
render={() => (
<ServicesPage
setValue={setValue}
setSelectedIndex={setSelectedIndex}
/>
)}
/>
<Route
exact
path={Routes.MOBILE_APPS}
render={() => (
<MobileAppsPage
setValue={setValue}
setSelectedIndex={setSelectedIndex}
/>
)}
/>
i would create a list like below
const list = [
{path: Routes.HOME, component: LandingPage},
{path: Routes.SERVICES, component: ServicesPage},
{path: Routes.MOBILE_APPS, component: MobileAppsPage}];
and i want to achieve below
list.map((obj) => (
<Route
exact
path={obj.path}
render={() => (
<obj.component
setValue={setValue}
setSelectedIndex={setSelectedIndex}
/>
)}
/>
))
When rendering a custom component, you must have its name Capitalized:
// Good
<Component/>
<Obj.Component/>
<Obj.component/>
// Bad
<component/>
<obj.component/>
<obj.Component/>
list.map(({ path, component: Component }) => (
<Route
exact
path={path}
render={() => (
<Component setValue={setValue} setSelectedIndex={setSelectedIndex} />
)}
/>
));
// Same
list.map((obj) => {
const { component: Component, path } = obj;
return <Route path={path} render={() => <Component {...}/>} />;
});
I use reach/router with custom protected route like this :
const ProtectedRoute = ({ component: Component, ...rest }) => (
localStorage.getItem('user_id') ? <Component {...rest} /> : <Redirect from="" to="/login" noThrow />
);
const LoginRoute = ({ component: Component, ...rest }) => (
localStorage.getItem('user_id') ? <Redirect from="" to="/home" noThrow /> : <Component {...rest} />
);
const PublicRoute = ({ component: Component, ...rest }) => (
<Component {...rest} />
);
<Router>
<LoginRoute component={Login} path="/login" />
<PublicRoute default component={Notfound} />
<ProtectedRoute component={landingPage} path="/home" />
<ProtectedRoute path="/" component={App} />
<ProtectedRoute component={UserList} path="user" />
<ProtectedRoute component={UserDetail} path="user/create" />
</Router>
i want this to be nested route with user/:id
<ProtectedRoute component={UserList} path="user" />
<ProtectedRoute component={UserDetail} path="user/create" />
what should i do?
I Feel like you're complicating things
const Routes = () => {
const [loggedIn, setLoggedIn] = useState(false)
useEffect(() => {
localStorage.getItem('user_id') && setLoggedIn(true)
}, [])
return (
<Router>
<LoginRoute component={Login} path="/login" />
<Notfound default />
{
loggedIn
? (
<>
<LandingPage path="/home" />
<App path="/" component={App} />
<UserList component={UserList} path="user">
<UserDetail component={UserDetail} path="create" />
</UserList>
</>
) : (
<Redirect from="" to="/login" noThrow />
)
}
</Router>
)
}
In case this didn't work as intended or you feel you want to use it in your way, do this
<Router>
...
<ProtectedRoute component={UserList} path="user">
<UserDetail path="create" />
</ProtectedRoute>
</Router>
No need of using ProtectedRoute HOC for UserDetail since it's already nested under ProtectedRoute
and in UserList use props.children to render UserDetail
class App extends Component {
render() {
let pathName=window.location.pathname;
console.log('pathName==>',pathName);
let loginhideheaderpath = pathName==="/" || pathName==="/login";
let securnetheaderpath = pathName==='/Contentlanding/Reports';
let gallerypath = pathName==='/Contentlanding/Gallerylanding'
return (
<>
{ securnetheaderpath ? <Securnetheader /> : ( loginhideheaderpath) ? null :(gallerypath) ? <Galleryheading /> : <Header /> }
<Router history={history}>
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/login" component={Login} />
<Route exact path="/Contentlanding" component={Contentlanding} />
<Route exact path="/Contentlanding/Birthdaylist" component={Birthdaylist} />
<Route exact path="/Contentlanding/Reports" component={Reports} />
<Route exact path="/Contentlanding/Gallerylanding" component={Gallerylanding} />
<Route component={Nodocumentfound} />
</Switch>
</Router>
</>
);
}
}
In my project i am using mutiple headers, i am rendering the header for components based on URL.
my condition is working fine. the problem is when i use the browser back button the header are not changing. any solution to fix this Thanks in advance.