ReactJs - redirect url - javascript

I am new to reactjs - and if I hit an error page on a subpage - because the url is wrong - I am looking to find a way to redirect the page to another.
So de/dienstleistungen/isdfisf -- spelt wrong
redirect to de/dienstleistungen
I've tried to write a function to handle this but no luck
if (!lang.serviceIntro[0][service]) {
console.log('undefined', this)
this.context.router.push('/de/dienstleistungen')
}
Failed context type: Invalid context router of type object supplied to PlainHeader, expected function.

are you using react-router? and if used which version are you on it?
Check out https://reacttraining.com/react-router/web/api/history which is currently on v4. This is my code
class App extends Component {
componentDidMount() {
let token = ... // achieve token
if (!token) {
this.props.history.push('/login');
}
}
render() {
....
}
}
my code in main page checking if not authenticated will redirect to login page programmatically. Props this.props.history will be passed by react router through .
Check the docs above for more information. Hope it help

As the error message says, you should declare contextTypes.router as an object, router was a function in older versions
static contextTypes = {
router: PropTypes.object.isRequired
}

Related

Redirecting in react-router-dom v6 in a non-JSX context

I'm trying to redirect a user from the route they are currently looking at to another route programatically. In my case, I am not in a JSX environment, and cannot use any kind of React hooks. How would I go about this?
I tried to use the code block below to redirect (tried using JSX), only to realize that it wouldn't work as it isn't in the context of the root router.
ReactDOM.render(<div>
<Navigate to="/" />
</div>, document.getElementById("redirect"));
I also want to try and redirect without using window.location.href = as that would cause the whole page to refresh, something I don't want to happen.
EDIT: As requested, I am trying to redirect to a page from an event that is emitted by Tauri and is handled by some TypeScript code on the front end. Using window.location.href isn't an issue in any case.
Here is an example of what I'm trying to do:
/**
* Sets up event listeners.
*/
export async function setupListeners() {
console.log("Setting up link event listeners...");
await listen("deeplink", onLinked);
}
/**
* Invoked when a deep link call is received.
* #param event The event.
*/
async function onLinked(event: Event<string>) {
const { payload } = event;
if (payload == "test:")
// redirect("/testPage");
}
See redirect:
import { redirect } from "react-router-dom";
const loader = async () => {
const user = await getUser();
if (!user) {
return redirect("/login");
}
};
(from the docs)

How to update navbar after a successful login in VueJS?

I am trying to "re-render" my navbar after the user logs in from the login page. I have certain nav links that will show depending on whether or not the user is logged.
Right now I am rendering those if I can find an user item on the localStorage:
`
Navbar.vue
<script>
export default {
data() {
return {
notLoggedInDropDown: false,
loggedInDropDown: false,
logged: localStorage.getItem('user') == null ? false : true,
user : {}
}
},
methods: {
closeSession() {
localStorage.removeItem('user');
localStorage.removeItem('token');
this.logged = false;
this.user = {};
},
},
mounted() {
var user = JSON.parse(localStorage.getItem('user'));
this.user = user;
},
}
</script>
And this is what I do after I login from the login page:
Login.vue
methods: {
async signIn(){
try {
const data = await login(this.username, this.password)
localStorage.setItem('user', JSON.stringify(data.user))
localStorage.setItem('token', data.token)
this.$router.push('/')
} catch (error) {
this.error.status = true
this.error.message = "Username or password failed."
}
}
},
`
I have tried to send emitters using mitt but navbar is not really a child component of the login page. I also have tried making the logged boolean a computed statement but it still does not re-render. I know that the reason it does not update is because the router.push method is not reactive, but I am unsure about what to try next. Also, my app does not use Vuex at the moment, can I integrate that easily into my Vue app? Any help welcome!
I think the best way is to use Vuex.
Create a variable in vuex, write it from Login.vue and export it to all components throuht a getter. From Navbar.vue you should get the vuex variable in a computed property and react to its value change when somebody logs in.
Otherwise, the recommended way to handle a login is through vue-router, you should take a look at the vue docs for it.
Good luck!
There are three solutions I know to work. One is not rerouting with the vue-router but with the browser's functionality. Something like location.replace(url);. Two is working by emitting from the login page to the application and then using a prop giving the information to the navbar. Three and what i usually prefer using vuex to get a shared store between components. Option one is the easiest and fastest, but option three makes your application more robust.

React: change url without rerender; using window.history?

I have a "settings" page in my react app. The page has several tabs rendering different parts of settings.
It would be better UX if a user can share urls with other users.
What I want is (inside "settings" page):
user A clicks a tab
url changes with a #tabname appended
user A send that url to user B, and user B open that url
user B sees the same tab as user A
But with react router, the whole page re-renders if the url changed:
import { withRouter } from "react-router-dom"
const MyComp = (props) => {
...
const onTabChange = () => {
// append #tabname here
props.history.replace(...); // or `push`
...
}
...
export default withRouter(MyComp)
}
After a lot of searches, I found a solution to use window.history:
const onTabChange = () => {
window.history.pushState(null, null, "#tabname");
...
}
This does the trick, but little information and explanation, and I'd love to know the consequences of using this trick.
Is this a valid solution (for a react app)? Will this cause any problem?
(PS. I know how to parse a url)
More details:
To be more specific, there is a AuthChecker wrapper for all pages. When react router's location changes, it checks for the route's allowed auths and current user's auth.
I've tried /path/:id and everything but all change location, so auth checked and page rerendered.
And I've given up a solution in react router and just want to know: is it safe to change url with window.history in a react app using react router to manage routes?
this question is already answerd at this post.
so it says window has a property called history and there is a method on history which helps you update the history state without react-router-dom understanding it.
like this:
window.history.replaceState(null, 'New Page Title', '/new_url');

How can I get cookie from browser in Next js (without use getServerSide or getInitialProps)?

I want to get my authToken which located in
cookies.
But when I tried to get it, I got undefined or something like this.
I wanted to use useContext and put _app in the context(to check if the user is authorized in child elements), but I can't get the cookie in any way.
I can get cookie in following code that located in adminPanel element, but I don't want to break the DRY principle. Maybe you can recommend me some methods to get global context for auth? (without next-auth or something like
export async function getServerSideProps(ctx) {
if (ctx.req) {
axios.defaults.headers.get.Cookie = ctx.req.headers.cookie
return {
props: {
cookie: ctx.req.headers.cookie ? ctx.req.headers.cookie : ''
}
}
}
I tried to get at least something similar to the authorization token in _app, but nothing worked (i also tried getServerSideProps).
export async function getInitialProps(ctx) {
return {
props:{
ctx
}
}
}
In this case I got ctx: undefined...
Maybe you can recommend me some methods to get global context for auth? (without next-auth or something like that)
There's a lot to this question, so forgive me if I fail to answer directly, please let me know if you need further elaboration.
Firstly, there is a helper package for using cookies in next: https://www.npmjs.com/package/next-cookies
Secondly, if you want to keep your getServerSideProps DRY, you can always make a reusable function or a HOC wrapper and load it into whichever pages need it.
Thirdly, getting the context is slightly different for _app.jsx than it is to regular pages. The page-context is wrapped in an app-context, like so:
import App from "next/app";
class MyApp extends App {
//...
}
MyApp.getInitialProps = async (appCtx) => {
const appProps = await App.getInitialProps(appCtx);
const { ctx } = appCtx;
console.log(ctx);
// todo: get your data from ctx here
};
But beware, this will kill the static optimisation for your entire site, so it's best to keep it to just each page that needs it.

ReactJS - Wait third party script response before render

I implemented J-Toker in my frontend app using React and flow (with a Rails API backend), in a similar way to this project react-flux-jwt-authentication-sample
The dashboard should only be accessed by logged in user. In order to do this, J-Toker calls my Rails API and return the loggedIn User (or not if no one is loggedIn...) that is accessible using Auth.user.
So I have my Dashboard component wrapped in an AuthenticatedComponent:
Dashobard.jsx
export default AuthenticatedComponent(Dashobard);
Here is my AuthenticatedComponent.jsx:
export default (ComposedComponent) => {
return class AuthenticatedComponent extends React.Component {
static willTransitionTo(transition) {
if (!LoginStore.isLoggedIn()) {
transition.redirect('/login', {}, {'nextPath' : transition.path});
}
}
...
}
Finally here is my LoginStore.jsx code:
import Auth from 'j-toker';
class LoginStore extends BaseStore {
...
isLoggedIn() {
return Auth.user.signedIn;
}
}
Everything works great except when I manually refresh the page. In this case, the Auth.user.signedIn return undefined even if the user is logged in and is redirected to the login page. I found that the problem comes from the fact that Auth.user is not yet loaded when LoginStore.isLoggedIn() is called because in this case Auth.user returns an empty object and if I wait a little (tested with a basic setTimeout) it returns the loggedIn user.
I am new to React.JS (using it for just a week now) and I'm not sure how to deal with this. I read A LOT of articles and cannot understand yet how React.JS is meant to be used, espacially with third party plugins (I also have a lot of problems using animation plugins but it's another story...).
Could someone help me on this?
It would be much appreciated :)
This happens because when you pass the configuration to J-Toker, the library will check for a stored token. In case it finds one it will validate the token with you API. This is why calling configure, it will return you a jquery Deferred object, which will be resolved after the validation has been done or rejected if there is no stored token. If the validation passes in you API the user object will be returned and set in Auth.user.
By following your example project you can fix this by rendering the component after the Deferred has been resolved.
var promise = Auth.configure({
apiUrl: 'your-api-host'
});
promise.always(function() {
router.run(function (Handler) {
React.render(<Handler />, document.getElementById('content'));
});
});

Categories