I got all my Routes in my App.js like this:
<Route exact path="/" component={Home} />
<Route path="/explore" component={Explore} />
<Route path="/register" component={Register} />
<ProtectedRoute path="/create" component={CreatePost} />
and I want to toggle an Success/Error Alert Component as Feedback but I want to display it above the whole app no matter which component is rendered right now. So I am stuck and don't know what is the best way to do so. I tried to write a function to toggle the Alert in App.js and export it but it didn't work for me to import it and change the state.
onShowAlert = () => {
this.setState({ showAlert: true };
};
You can use render assignment and pass your feedback trigger to the component. Is this what you are asking?
function myTigger(){ console.log('triggered') }
<Route exact path="/" render={ () => <Home trigger={myTigger} />} />
<Route path="/explore" component={Explore} />
<Route path="/register" component={Register} />
<ProtectedRoute path="/create" component={CreatePost} /
If you're trying to avoid passing the toggler as a prop, then create an AlertContext:
https://codesandbox.io/s/great-moon-93c94?file=/src/AlertContext.js
Related
I'm trying to render the params in the url as an h2 in in the website. But even when I try console.log useParams is empty.
Here's my Router.js file
const Webpages = () => {
return (
<Router>
<Routes>
<Route exact path="/" element={Home()} />
<Route exact path="/comics" element={Comics()} />
<Route path='/comics/:comicId' element={Comic()} /> <--------------
<Route exact path="/portfolio" element={Portfolio()} />
<Route exact path="/blog" element={Blog()} />
<Route exact path="/contact" element={Contact()} />
<Route exact path="/store" element={Store()} />
<Route path="*" element={NotFound()} />
</Routes>
</Router>
);
};
export default Webpages;
Here's my comic component
import React from 'react';
import NavBar from '../../components/NavBar';
import { useParams } from 'react-router-dom';
function Comic() {
let { comicId } = useParams();
console.log(comicId);
return (
<div>
<NavBar />
<p>{comicId}</p>
</div>
)
}
export default Comic
The page element when I go to a random comic works fine, like localhost:3000/comics/465456 but the tag is empty and the console log is undefined, it's also undefined if I just try to console log useParams()
You are directly invoking the React function. Directly invoking React functions is not how React works.
The Route component's element prop expects a React.ReactNode, a.k.a. JSX. Pass the components as JSX. The JSX is transpiled down to vanilla Javascript and the React framework handles calling your function within the confines of the React component lifecycle.
Example:
const Webpages = () => {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/comics" element={<Comics />} />
<Route path='/comics/:comicId' element={<Comic />} />
<Route path="/portfolio" element={<Portfolio />} />
<Route path="/blog" element={<Blog />} />
<Route path="/contact" element={<Contact />} />
<Route path="/store" element={<Store />} />
<Route path="*" element={<NotFound />} />
</Routes>
</Router>
);
};
I am using ReactJS, redux, and react-router. I am using localStorage to log in users automatically. My App.js looks like this:
` <Router>
<Provider store={store}>
<div className="App">
<Route path="/" component={NavBar} />
<Route exact path="/" component={Home} />
<Route exact path="/list" component={RoadmapList} />
<Route path="/roadmap" component={OneRoadmap} />
<Route path="/search" component={Search} />
<Route exact path="/add" component={RoadmapAdder} />
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route
exact
path="/savedRoadmaps"
component={SavedRoadmapsView}
/>
<Route path="/profile" component={AuthorProfile} />
<Route exact path="/account/edit" component={Profile} />
</div>
</Provider>
</Router>`
I previously did auto-authentication in my NavBar component since NavBar will be in every single URL because of the <Route path="/" component={NavBar}/>, I thought I could've just used NavBar to auto-login my users using a redux action called loginUser and then update a few redux states like isAuthenticated and user_info. The problem is that if I were to render NavBar and let's say SavedRoadmapsView, SavedRoadmapsView wouldn't get the redux states immediately since it runs parallel with NavBar.
I have tried to login Users automatically in App.js, like:
` async componentDidMount() {
var email = localStorage.getItem("email");
var password = localStorage.getItem("password");
var userData = { email: email, password: password };
await loginUser(userData);
}`
It didn't seemed to work. Could it be that loginUser is a redux action and can't be used outside of Provider? What are your insights on this? Thanks in advance.
Being a beginner in reactJS, I want to know how to hide parent component when i route to child component URL
Assume a scenario:
User is at "/house" as this:
<Route path="/house" component={House} />
when user clicks a house grid he navigates to "/house/flat/:flatID". Inside House component
<Route
path={`${this.props.match.url}/flat/:flatId`}
render={() => <div>Each Flat details</div>}
/>
then both child and parent components are visible like this:
So what i want is to show only flat component when user navigates to "/house/flat:FlatId". Please suggest me anything that helps ! Any links to article so that i can learn and achieve such functionality.
Code:
App.js
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/account" component={Account} />
<Route path="/gharjagga" component={GharJagga} />
</Switch>
House.js
onGharGridClick= id => {
<Redirect to={`${this.props.match.url}/flat/${id}`} />;
};
return (
<Route
path={`${this.props.match.url}/flat/:fkatId`}
render={() => <div>Ghar Each</div>}
/>
);
You can achieve it different ways
define routes in the parent component, I think this is the best option.
<Switch>
<Route path="/account" component={Account} />
<Route path="/house/flat/:flatId" component={FlatComponent}/>
<Route path="/house" component={House} />
<Route path="/" component={Home} />
</Switch>
Note: instead of using exact, order your routes based on priority, that will make the route to redirect to next matching route if any typo in the route entered
You can make House as separate route component, and nest the routes inside that component
// Routes
<Switch>
<Route path="/account" component={Account} />
<Route path="/house" component={House} />
<Route path="/" component={Home} />
</Switch>
// House component
class House extends React. Components {
render() {
return (
<Switch>
<Route path="/house/flat/:flatId" render={() => <div>Each Flat details</div>} />}/>
<Route path="/house" component={HouseGridComponent} />
</Switch>
)
}
}
you can check whether the route has flatId and hide the elements, in your House component you can check this.props.match.params.flatId, if the flatId is set you can hide that House Component.
// House Component
class House extends React. Components {
render() {
return (
<div>
{
!this.props.match.params.flatId?
<h1>House Component</h1>:
null
}
<Route path={`${this.props.match.url}/flat/:flatId`} render={() => <div>Each Flat details</div>} />
</div>
)
}
}
The solution is to raise "/house/flat/:flatId" to the same level as "/house".
<Switch>
<Route exact path="/" component={Home} />
<Route path="/account" component={Account} />
<Route path="/house/flat/:flatId" render={() => <div>Each Flat details</div>}/>
<Route path="/house" component={House} />
</Switch>
I am trying to group some of my routes together with React Router v4 to clean up some of my components. For now I just want to have my non logged in routes group together and my admin routes grouped together but the following doens't work.
main.js
const Main = () => {
return (
<main>
<Switch>
<Route exact path='/' component={Public} />
<Route path='/admin' component={Admin} />
</Switch>
</main>
);
};
export default Main;
public.js
const Public = () => {
return (
<Switch>
<Route exact path='/' component={Greeting} />
<Route path='/signup' component={SignupPage} />
<Route path='/login' component={LoginPage} />
</Switch>
);
};
export default Public;
The Greeting component shows at "localhost:3000/", but the SignupPage component does not show at "localhost:3000/signup" and the Login component doesn't show at "localhost:3000/signup". Looking at the React Dev Tools these two routes return Null.
The reason is very obvious. for your route in main.js, you have specified the Route path of Public component with exact exact path='/' and then in the Public component you are matching for the other Routes. So if the route path is /signup, at first the path is not exact so Public component is not rendered and hence no subRoutes will.
Change your route configuration to the following
main.js
const Main = () => {
return (
<main>
<Switch>
<Route path='/' component={Public} />
<Route path='/admin' component={Admin} />
</Switch>
</main>
);
};
export default Main
public.js
const Public = () => {
return (
<Switch>
<Route exact path='/' component={Greeting} />
<Route path='/signup' component={SignupPage} />
<Route path='/login' component={LoginPage} />
</Switch>
);
};
Also when you are specifying the nested routes these should be relative to the parent Route, for instance if the parent route is /home and then in the child Route you wish to write /dashboard . It should be written like
<Route path="/home/dashboard" component={Dashboard}
or even better
<Route path={`${this.props.match.path}/dashboard`} component={Dashboard}
Did anyone know how to create for any path that ends with '/popup-image-:id' ? i have website where each image could be opened in popup on any page. So, if i couldn't implement '/popup-image-:id' i have to double each route in my website to place inside. I would like avoid redundance and fragility.
my current routing:
<Router history={browserHistory}>
<Route path="/" component={Base}>
<Route path="profile" component={Profile}>
<Route path="popup-image-:id" component={Full_Piture} />
</Route>
<Route path="feed" component={Feed_List}>
<Route path="popup-image-:id" component={Full_Piture} />
</Route>
<Route path="user-:id" component={User_Page}>
<Route path="popup-image-:id" component={Full_Piture} />
</Route>
</Route>
</Router>
As u can see i had to produce a lot of duplicated code. If i could write something like <Route path="*/popup-image-:id" component={Full_Piture} /> it will be much cleaner and solid code
Is the parent <Route> also supposed to match? If it isn't, you should be able to use the ** syntax.
<Route path="/**/popup-image-:id" component={Full_Picture} />
If the parent <Route> should also match, you could create a <RouteWithPopup> component that returns a <Route> which has the <Route path='popup-image-:id'> as its child.
const RouteWithPopup = (props) => {
return (
<Route {...props}>
<Route path="popup-image-:id" component={Full_Picture} />
</Route>
)
}
Then you could turn your route config into:
<Router history={browserHistory}>
<Route path="/" component={Base}>
<RouteWithPopup path="profile" component={Profile} />
<RouteWithPopup path="feed" component={Feed_List} />
<RouteWithPopup path="user-:id" component={User_Page} />
</Route>
</Router>