How to use dynamic routing in React? - reactjs

I am developing a dashboard application using React. I am having some issues understanding react-router. How can we use the dynamic route and render a component?
My app has a few static routes like /user, /profile and /dashboard. I am rendering User, Profile and Dashboard components for the routes. When the user logs in, the server will send JSON response which contains, user id, type, and other fields. I want to change the routing path to /dashboard/45 (45 is userId) for this user after a successful login. In the end, the Dashboard component will render different elements based on userId and userType.
<Route
path='/dashboard'
exact={true}
render={(props) => <Dashboard {...props} user={user} handleChildFunc=
{this.handleChildFunc}/>}/>
What is missing in this code? I am not sure what to google or which tutorial to follow. Thanks in advance.

This is what I use:
<Route exact path='/feed/:id' component={
(props) =>
<Feed
postId={props.match.params.id}
/>
}/>
Then the id can be accessed inside Feed using props.postId e.g.
constructor(props) {
super(props);
if (props.postId) {
// do something
}
}

Related

Redirect from email link to page

So I am currently implementing a "reset password" feature on my website. My application uses JWT for authentication. The application uses React (React Hooks, not components) on the frontend, with react-router-dom for the routing, and Flask on the backend.
The backend functionality works fine. A user fills in an email address of the email they wish to reset the password of, and then the backend sends an email with a link to that address they can click (at the moment, once clicked, it just returns an OK response and does nothing else).
My question is, after the link is clicked in their inbox, I want the user to be forwarded to a /change_password page where they can fill out a new password.
Once the email link is clicked, how can I then go from the Flask backend, to rendering a specific route in React?
I am using react-router-dom client-side routing throughout my application.
I am only asking as it seems a bit strange to have a mix of server-side and client-side rendering for an application. If I can forward to a page in in React, that would be nice.
So my routes are called by index.jsx
index.jsx
ReactDOM.render(<AppRouter/>, document.getElementById("app"));
routes.jsx
const AppRouter = () => {
const [user, setUser] = useState(null);
const providerValue = useMemo(() => ({user, setUser}), [user, setUser]);
return(
<BrowserRouter>
<Route exact path='/' component={LandingPage} />
<Switch>
<UserContext.Provider value={providerValue}>
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
<Route path="/forgotten" component={ForgottenPage} />
<PrivateRoute path="/home" component={UserApp} />
</UserContext.Provider>
</Switch>
<Redirect from="*" to="/" />
</BrowserRouter>
)
}
At the moment, Flask just renders index.html which has 1 tag element id of app.
Any advice would be great.
Sorry not 100% understanding what your current setup is
Server Side Rendering
Yes exactly, send it over then when the button is clicked the token and user id should be sent to the backend and after verification the backend sends back a template which will then be filled out and sent to the api with the token and user ID again (at least how I would do it)
Client Side Rendering
The way I would go about this is in my Router have
<Route path "/recoverpassword/:tempToken">{recoverComponent}
And then have the link take you to app.com/recoverpassword/{tempToken}
Then set up a componentDidMount on the recoverComponent which calls the backend making sure the link is active and the token is valid. If it is then use the token to set up a new password.
You could try to use a listener of some sort but if they switch browsers to go to their email inbox just as an example then this won't work. Don't recommend that at all

How to redirect to an external url in React?

I am trying to redirect to an external URL in a react component.
I am verifying when the component is loaded if it contains an access_token in the local storage. If it does not exist I want to redirect to an auth provider to perform login and then to store the token when it redirects back to me.
However I found that assigning a value to window.location or window.location.href or using window.location.replace(someUrl) it does not work, it simply appends the new url to my application url.
Here is my react component where I am doing this:
class App extends React.Component {
componentDidMount() {
if (!localStorage.getItem('access_token')) {
window.location.replace(someUrl)
}
}
render() {
return (
<HashRouter>
<React.Suspense fallback={loading()}>
<Switch>
<Route path="/" name="Home" render={props => <DefaultLayout {...props}/>}/>
</Switch>
</React.Suspense>
</HashRouter>
)
}
}
Is there a different way on how the redirect to an external URL should be done in React?
I also tried this one and it does not work, it appends the external URL to the one of my application:
React-Router External link
Use React Router Redirect component and provide address in to attribute.
<Redirect push to="/somewhere/else" />
https://reacttraining.com/react-router/web/api/Redirect

Load login page without Sidebar, Navbar and Dashboard in React

How to load login page without sidebar, navbar and dashboard?
extract your <div id="wrapper">...</div> into a separate component.
Add a route for your wrapper with no path
<Route component={Wrapper} />
Wrap all the routes in <Switch> from react-router.
<Switch>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/forgot-password" component={ForgotPassword} />
<Route component={Wrapper} />
</Switch>
Switch will mean that only the first matching route is rendered.
A route with no path will match any path.
You could setup a flag in your redux store to determine whether these components should be displayed.
Setup the initial state in your reducer, and have your Sidebar, Navbar, and Dashboard subscribe to that flag and use conditional rendering in each of those components.
So your redux state would maybe have something like:
showPageContent: false
In each of your components, have them subscribe by connecting them and passing in a mapStateToProps like:
const mapStateToProps = (state) => ({
shouldRender: state.showPageContent
})
export default connect(mapeStateToProps)(Sidebar)
Then in the render for each of your components:
render() {
this.state.shouldRender ? <Sidebar> : null
}
OR
render() {
if (this.state.shouldRender) {
<Sidebar>
}
}
You would need to implement an login action that set the showPageContent flag to true once logged in successfully.
Example:
https://www.sohamkamani.com/blog/2017/03/31/react-redux-connect-explained/
Well, I will suggest that you should have separate container for Credentials and Login and Signup should be the components.
That page should have public routing, which means it could be viewed by general public. Your Navbar, Sidebar and Dashboard should be other components and should not be included in Login and Signup components.

How to handle infinite Links with react

I'm currently building a recipe book website based on ReactJS and react-router.
All my informations is saved in JSON and I'm handling all that using axios.
Now my question is, I have a grid with all my recipes, when I click on one is uses a Link to redirect me to another page, like this :
<Link to={'/' + name} className="recipe-styler" id={name}>
How can I redirect this so it will open a page and load the information of that.
I was thinking of just redirecting it to /detailedRecipe for example and parsing all the informations throught the Link, but I don't know if that is possible.
This is a combination of dynamic routing with react-router-dom and using match params.
First, let's say you have 3 routes in the app, List view, Details view and a fallback route (error page for example). It would look something like this:
<Router>
<Switch>
<Route exact path="/recipes" component={ListComponent} />
<Route path="/recipes/:id" component={DetailsComponent} />
<Route component={ErrorPage} />
</Switch>
</Router>
Now, you can set the links inside your grid to be something like this:
<Link to={`/recipes/${item.id}`} className="recipe-styler" />
Finally, when you click on the link, and router redirects to you the DetailsComponent, you can get the link id like this.
export class DetailsComponent extends React.Component {
componentDidMount() {
const { match } = this.props;
if (match) {
// This line is pseudocode.
// Use the id to get the item details from api, redux or wherever.
api.get(params.id)
}
}
render() {
...
}
}
Router will injects the match.params object when it resolves the route. Prop name from the params object depends on how you named it in the router declaration e.g.
<Route path="/recipes/:recipeId" component={DetailsComponent} /> // params.recipeId
<Route path="/recipes/:id" component={DetailsComponent} /> // params.id

Handle incoming query params from firebase URL using react + react-router

I'm attempting to hook up email/pw auth with email verification using Firebase. I'm using React + Redux + React-Router. The account creation is going fine - the user account is created in the Firebase user database, but the issue I'm having is in trying to capture the "mode" and "oobCode" from the link that Firebase provides in its email verification (the URL format is .../verify?mode=foo&oobCode=bar). I have Firebase linking (for the moment) to localhost:3000/verify, so in my routes, I tried to add a route path like this:
<Router history={ browserHistory }>
<Route path="/" component={ MainApp }>
<IndexRoute component={ LandingPage } onEnter={ redirectIfLoggedIn } />
<Route path="verify/:mode/:oobCode" component={ LandingPage } onEnter={ redirectIfVerified } />
// other routes
</Route>
</Router>
However, when I click on the URL in the e-mail, I get an error page. Essentially, all I'm trying to do is intercept that incoming e-mail link, check if the mode & oobCode are correct using Firebase's applyActionCode, then either send the user to the main logged-in page or to an error page. Any idea what I'm missing here?
The url format you receive is .../verify?mode=foo&oobCode=bar.
Route should look like this -
...
<Route path="verify" component={ LandingPage } onEnter={redirectIfVerified } />
...
mode and oobCode are query params. You can get these values in your component from the location object injected into the props.
this.props.location.query = {mode: "foo", oobCode: "bar"}

Resources