In React How to pass Id to another page class component - reactjs

I need to pass the Id to another Page using Class components. this.props.match.params.group_Id it returns undefined.Here is my code
#page1
<Link to={"/GroupsDetail.js/?group_Id="+item.group_Id}}>Details</Link>
#page2
submit() {
let Id= this.props.match.params.group_Id;
console.log(Id);
let url = 'http://localhost:0000/api/Group/GroupDetailsDisplay?group_Id='+Id;
}
Need to pass that Id into API.Please share your Idea. Thank you

const url = new URL(window.location.href);
const Id = url.searchParams.get("group_Id");

react-router-dom only handles the path parts of the URL, it doesn't do anything with queryString parameter other than include them in the location object.
Locations represent where the app is now, where you want it to go, or
even where it was. It looks like this:
{
key: 'ac3df4', // not with HashHistory!
pathname: '/somewhere',
search: '?some=search-string',
hash: '#howdy',
state: {
[userDefined]: true
}
}
Access the location prop and pass the search property to a new URLSearchParams to parse the queryString.
submit() {
const { location } = this.props;
const query = new URLSearchParams(location.search);
const Id = query.get('group_Id');;
console.log(Id);
let url = 'http://localhost:0000/api/Group/GroupDetailsDisplay?group_Id='+Id;
}
If you wanted to keep the group id on the route's match params then you'll need to define the route path like path="/GroupsDetail.js/:Id", and link to it as <Link to={`/GroupsDetail.js/${item.group_Id}`}>Details</Link>.

Related

Passing props via route Sveltekit

I am using Svelte+Sveltekit without any routing libraries.
What I would like to do is pass an object to a route, from another page via an <a> tag (or otherwise).
On one page I have a list of objects, for each object I render an item:
// home.svelte
<-- start of page -->
{#each users as user}
<a href="users/{user.username}" sveltekit:prefetch/>
{/each}
<-- end of page -->
The user object above has a few key-value pairs I want to render in the /users/{username} - which is created as a slug route:
// routes/users/[slug].svelte
<script context="module">
export async function load(ctx) {
let data = ctx.page.params;
// I'd like to be able to pass the whole user object from the <a> tag in home.svelte, and access it from ctx.page.params if possible
return { props: { slug: data.slug, user: data.user } }
}
</script>
<script>
export let slug;
export let user;
</script>
<div>
<h1>{slug}</h1>
<h1>{JSON.stringify(user)}</h1>
</div>
Is it possible to do it this way, or do I need a different approach/routing library?
I think it okay to do this. You can get the {user.username} in users/[slug].svelte by export the load function with 'page' parameter. You may try to modify it as below. You may check out the svelteKit online document here
export const load = ({ page }) => {
var username = page.params.slug; //slug refer to [slug].svelte
return {
props: {
user: GetUserByName(username);
}
};
...
You can use the 'query' param
// home.svelte
//use a query string converter library
<a href="users/{user.username}?{objectToQuery(user)}" sveltekit:prefetch/>
then in load function
return {
props: {
slug: page.params.slug,
user: queryToObject(page.params.query)
}
}
but your safest bet is to use a store.
<div>
<h1>{slug}</h1>
<h1>{JSON.stringify($user)}</h1>
</div>
In which case you dont need to pass anything.

React location.pathname to (custom) title

I am currently developing in a react project and I want to show the current page title in my header. To currently do this, I am using the props.location.pathname and a switch-case to get the desired output.
This looks something like below.
var currentPathname = this.props.location.pathname;
switch (currentPathname) {
case '/':
return 'Home';
}
The amount of paths are adding up and I do not want to make one big switch-case. So I was wondering, if there is any better way to set a (custom) title depending on a path. I expected something to be available in the react-router but I have not found such a thing yet.
Any insights are welcome.
Use a map instead of using switch statement.
const {pathname} = this.props.location;
const pathToTitleMap = {
"/": "Home",
"/something": "Amazing page title"
}
document.title = pathToTitleMap[pathname]
I'd say that you don't really have a different option. You'll need some place that maps the path to the title (If your titles cant be retrieved from the path name itself). If you want to make it look a bit shorter, you could use the ternary operator like this:
const path = this.props.location.pathname;
const title = path == '/' ? 'Home' : path == '/contact' ? 'customContactTitle' ...
You could make a hook out of it, like 'getTitle' and then just import it in your pages.
I think your solution looks clean enough. As long as you separate the logic for getting the path and its title into a single file (hook) it should be maintainable since you normally don't add static paths too often.
If you're using Next.js, you could store the paths and their corresponding titles in a database or CMS and then fetch them once during build time (with Next's getStaticProps) if that would help with maintainability.
Have you thought about making the paths equal to or related the title so you would only need to display a custom title once on the index '/' page and otherwise retrieve it from the path?
You can have a map of paths and title
const pathToTitleDictionary = {
"/": "Home",
"/about": "About",
...
}
function PageTitle({path}) {
useEffect(() => {
document.title = pathToTitleDictionary[path];
},[path]);
}
Use <PageTitle path={this.props.location.pathname} /> to update the title
You can do it by maintaining a JSON like
var titleForRoutes=[
{
route:"/", //route
title:"Home", //title to show on header
component:HomePage //React Component
},
{
route:"/Login",
title:"Login",
component:LoginPage
}
]
then in routes declare routed by iterating on that Json and on the other hand you can show the title using the same JSON.
Thank you.
I use a custom element to ensure my paths and titles are tidy and next to each other. While a little longer than some of the other answers, it keeps everything inside properties. Could likely be improved by using function component for Page.
<CustomRoute
path="/path/is/here"
component={ComponentHere}
title="Title goes here"
/>
/* * * * * * * * * * * * * * */
export const CustomRoute = ({ component = null, title = null, ...props }) => {
return (
<Route
{...props}
render={
props2 => <Page {...props2} component={component} title={title} />
}
key={props.path}
/>
);
};
class Page extends Component {
componentDidMount() {
document.title =
(this.props.title ? this.props.title + ' - ' : '') + 'Website Name';
}
render() {
const { component, ...props } = this.props;
const PageComponent = component;
return <PageComponent {...props} />;
}
}

React router is not taking ID in Link

I am working on project which is based on Firebase and React JS, i want to set ID in Link in Route Component but its returning me undefined,
It goes like, first List of Trainers Page and then Edit Trainer (specifically)
Main Component Look like this where i am giving my routes
<Route path= '/listOfTrainers' component={ListOfztrainers} />
<Route path='/editTrainer/:UID' component={EditTrainer} />
Then there is a list of trainer page, where i am showing list of trainer in table. One of its column in Edit Profile where i am giving link like below
Cell: <Link to= {`/editTrainer/${trainer.UID}`}>Edit</Link>
When i click on any trainer's row Edit Profile, it return me undefined in url
And when my self add ID which is firebase UID in url, it gives me correct result like
I am dropping code below of edit Trainer,
componentDidMount(){
const id = this.props.match.params.UID;
console.log(id);
firebase.database().ref(`Users/Trainers/` + id).on('value', (snapshot) => {
var trainer = snapshot.val();
this.setState ({
trainer
}, console.log(trainer))
})
}
Can anybody explain what I am doing wrong here in routing
to solve this problem you need to make sure that your trainer data fetched and parsed on DOM correctly like so :
componentDidMount(){
const id = this.props.match.params.UID;
console.log(id);
firebase.database().ref(`Users/Trainers/` + id).on('value', (snapshot) => {
var trainer = snapshot.val();
this.setState ({
trainer
}, console.log(trainer))
})
}
render() {
let {trainer} = this.state;
return (
<>
// in this way you can make sure that data parsed correctly on your dom elements
{trainer && <Link to= {`/editTrainer/${trainer.UID}`}>Edit</Link>}
</>
)
}

How can I pass a URL querystring variable dynamically to a composed graphql query in react?

I am attempting to build a component using date from a graphql query but cannot see how dynamically supply a variable if it is not available in props when my component is created. eg. I have:-
class UsageComponent extends Component {
render() {
const params = this.queryStringParse(window.location.href);
const queryStringImageId = params.id;
const imageDetailsResults = this.props.getImageDetails.imageByImageId
(etc...)
}
}
const GET_IMAGE_DETAILS_QUERY = gql`
query getImageDetails($imageId: Int!){
imageByImageId(imageId:$imageId) {
filename
originalFilename
width
height
description
(etc...)
}
}
`;
export default compose(
graphql(GET_IMAGE_DETAILS_QUERY, {name: "getImageDetails", options: props => { return { variables: { imageId: 123456 }}; }}),
graphql(GET_PUBLICATIONS_QUERY, {name: "getPublications"})
)(ImageBrowser);
Which works fine. i.e. imageDetailsResults is populated and I can use the data subsequently in the render function.
However I would like to be able to replace that hard set "imageId: 123456" in the composed graphql with the queryStringImageId value I get in the component render.
I don't think I am able to set this a props value as I'm coming to this component page from a redirected url:-
<Switch>
<AuthRoute path="/image" component={ImageBrowser} token={token} />
</Switch>
Any suggestions would be much appreciated!
You're probably looking for a method to use urls like /image/123456.
With react-router-dom you can define route with param:
<AuthRoute path="/image/:id" component={ImageBrowser} token={token} />
This way component gets router's prop passed in, match.params.id in this case ... and we're only one step away from final param passing:
export default compose(
graphql(GET_IMAGE_DETAILS_QUERY, {
name: "getImageDetails",
options: props => {
return { variables: { imageId: props.match.params.id }};
}}),
graphql(GET_PUBLICATIONS_QUERY, {name: "getPublications"})
)(ImageBrowser);

How can I desctructure items out of an object that is returned from a React hook using Typescript?

I have a component that needs to tap into the React Router query params, and I am using the use-react-router hook package to access them.
Here is what I am wanting to do:
import React from "react;
import useReactRouter from "use-react-router";
const Foo = () => {
const { id } = useReactRouter().match.params;
return (
<Bar id={id}/>
)
}
The issue is that this throws the following error in VS Code, and at compile time:
Property 'id' does not exist on type '{}'.ts(2339)
I have found that if I refactor my code like so:
const id = match.params["id"], I do not get the error, but I feel like this is not the correct approach for some reason. If someone could point me in the right direction, I would appreciate it.
I figured it out. The solution was to include angle brackets between the hook's name and the parenthesis, like so:
const { match } = useRouter<{ id: string }>();
const { id } = useRouter<{ id: string }>();
Or if you prefer nested destructuring:
const { match: { params: id } } = useRouter<{ id: string }>();
You can try to give default value to params
const { id } = useReactRouter().match.params || {id: ""};
It may be possible that params to be null at initial level
The code is insufficient.
However, at first glance,
// right way
const { history, location, match } = useReactRouter()
// in your case
const { match: { params : { id } } } = useReactRouter()
// or
const { match } = useReactRouter()
const { id } = match.params
now, try to console the value first.
Also, please try to pass the props to a functional component from it's container, since it's more logical.
From your comment below, i can only assume you solved it. Also, it's recommended to handle possible undefined values when you use it.
{ id && id }
However, the first step should've been consoling whether it has value in it,
console.log('value xyz', useReactRouter())

Resources