Reputation: 461
I'm struggling to find the right type for this situation. This is a simplified version of redirecting after login. The following produces a compiler error:
Property 'from' does not exist on type '{} | { from: { pathname: string; }; }'.
Adding as any
to the use of location.state
fixes the compiler error but it's ugly and the linter complains.
import React from "react";
import { useLocation } from "react-router-dom";
const AuthLayer: React.FC = (props) => {
const location = useLocation();
const { from } = location.state || { from: { pathname: "/" } };
return <p></p>;
};
export default AuthLayer;
Upvotes: 35
Views: 59331
Reputation: 1
If you are using React Router v6, the useLocation
hook does not accept a generic parameter directly as it did in some custom or modified type definitions or potentially older versions. Instead, you should define the state type separately and use it where needed.
Hereβs how you can do this correctly
import { useLocation } from 'react-router-dom';
interface LocationState {
from: string;
}
const MyComponent: React.FC = () => {
const location = useLocation();
const state = location.state as LocationState; // Type assertion here
return (
<div>
{state && <p>From: {state.from}</p>}
</div>
);
};
export default MyComponent;
Upvotes: 0
Reputation: 746
In react-router-dom version 6, it can be done like that
const locationState = useLocation().state as {id: string};
const id = locationState.id;
Upvotes: 2
Reputation: 1
If you send only one thing, What about using useParams instead of useLocation?
function routeDetails(id: string) {
history.push({
pathname: `/details/${pathname}`,
});
}
const { id } = useParams<{ id: string }>();
You can use useParams simply. It has key 'id' that is from history pathname.
Upvotes: -4
Reputation: 3092
This will be a little type-safe since it will return undefined
if from
is not in the object instead of throwing an error.
import React from "react";
import { useLocation } from "react-router-dom";
type LocationState = {
from: {
path: string;
}
}
const AuthLayer: React.FC = (props) => {
const location = useLocation();
// πππ
const from = (location.state as LocationState)?.from;
return <p></p>;
};
export default AuthLayer;
Upvotes: 3
Reputation: 615
export interface LocationParams {
pathname: string;
state: your_state_data_type;
search: string;
hash: string;
key: string;
}
//...
const location = useLocation<LocationParams>()
or create a generic that u can use any where
// types.ts
export interface LocationParams<Data> {
pathname: string;
state: Data;
search: string;
hash: string;
key: string;
}
// App.tsx
import { LocationParams } from './types.ts'
// ...
const location = useLocation<LocationParams<your_data_here>>()
Upvotes: 2
Reputation: 271
Type Assertion would work here.
import React from "react";
import { useLocation } from "react-router-dom";
type LocationState = {
from: {
path: string;
}
}
const AuthLayer: React.FC = (props) => {
const location = useLocation();
const { from } = location.state as LocationState;
return <p></p>;
};
export default AuthLayer;
Also, remember to define the type, as per your requirements.
For example, you might be using navigate(state.from)
.
For this Define the type as -
type LocationState = {
from : string;
}
Upvotes: 27
Reputation: 389
You can use Location from 'history'.
import React from "react";
import { Location } from "history";
import { useLocation } from "react-router-dom";
const AuthLayer: React.FC = (props) => {
const location = useLocation<Location>();
const { from } = location.state || { from: { pathname: "/" } };
return <p></p>;
};
export default AuthLayer;
Upvotes: 13
Reputation: 7428
You can create a particular type or interface to describe your location state and then use it when calling a useLocation
hook:
import React from "react";
import { useLocation } from "react-router-dom";
interface LocationState {
from: {
pathname: string;
};
}
const AuthLayer: React.FC = (props) => {
const location = useLocation<LocationState>();
const { from } = location.state || { from: { pathname: "/" } };
return <p></p>;
};
export default AuthLayer;
Upvotes: 36