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

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"}

Related

Redirect is not working properly in React

Here is my link of describing my first problem React page is not redirecting and code.
this code works perfectly fine but problem here is that when i successfully signup and then if i manually do to "/signUp" then for a less amount time(<1 sec)it shows signup screen. This should not be done it should straightly direct me to "/home". Any solution for this?
You would need to conditionally render routes according to whether the user is authenticated.
You will need to connect your redux store to the component that renders the routes and get the user from the redux store.
Here is an example:
import { Switch, Route, Redirect } from 'react-router-dom'
...
<Switch>
{user
?
// the user is autenticated
<>
<Route path="/home" component={HomePage} />
<Redirect to="/home" />
</>
:
// the user is not autenticated
<>
<Route path="/signUp" component={SignUp} />
<Redirect to="/signUp" />
</>
}
</Switch>
...
What this example will do is the following:
if the user is authenticated:
the user can navigate to the /home route
if they go to a different route, it will redirect them to /home
if the user is NOT authenticated:
the user can navigate to the /signUp route
if they go to a different route, it will redirect them to /signUp
I am using <>...</> which is equivalent to <React.Fragment>, which allows you to include adjacent elements in it, which is otherwise not allowed

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

How to use dynamic routing in React?

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
}
}

React account activation

I'm trying to figure out how to get the account activation link to React.
The Rails API sends an account activation URL as follows:
http://localhost:8080/users/confirm?token=480a476e6be366068dff
I would like to setup a React action that POSTs that token to the API and then a component will render a "account activated" message.
I am currently stuck on 2 issues:
How to directly open the above link in the browser? I'm getting a "Cannot GET /users/confirm" error message. I read that browserHistory is supposed to solve the problem of directly calling React URLs but I'm not sure how to implement it.
How to capture the token from the link? Is "/users/confirm/:token" the correct approach?
routes.jsx:
export default (
<Route history={browserHistory} path="/" component={App}>
<IndexRoute component={HomePage} />
<Route path="/users/login" component={LogInPage} />
<Route path="/users/register" component={RegisterPage} />
<Route path="/users/confirm/:token" component={ConfirmPage} />
</Route>
);
Whatever web server you're using to serve the react code needs to handle that route too. So if you're rendering the html page that bootstraps the react code with rails, add the route to the routes.rb, and have it render the file that loads your bundle.
Now in order to have the token come as a parameter like that:
<Route path="/users/confirm/:token" component={ConfirmPage} />
You'll need to have the rails api direct to it in the same way:
http://localhost:8080/users/confirm/480a476e6be366068dff
If you need to use the query string, update the route in react:
<Route path="/users/confirm" component={ConfirmPage} />
Then in the confirm page, get the token from the query string itself. You can do this in a few ways. I haven't tried it, but I believe react router parses it for you. In the ConfirmPage, access it by:
this.props.location.query.token
Router for Did You have an account? in Material UI ReactJS
handleClickSignIn() {
this.props.history.push("/Register");
}
return(<div><p style={signstyle} > Don't have an account yet?
< a href onClick={this.handleClickSignIn.bind(this)} >Join Register</a>
</p></div>)

Resources