If condition to change route using React Router V4 - javascript

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

Bind slug like the first URL segment

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>

React router not working on live production

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.

iterating on react components

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 {...}/>} />;
});

#reach/router nested protected route

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

using Multiple header in react router

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.

Categories

Resources