'Passing props to dynamically rendered components in React

I have a page that is displaying several of my star components that each have their own name and a prop called starType I am generating several different of these stars with the following code

if (num > 0) {
        return (
          <div className="starWrapper">
            <Star
              name={`${makeid()}`}
            
              starType={`${starList[Math.floor(Math.random() * 6 + 1)]} ${posList[Math.floor(Math.random() * 9 + 1)]}`}
            ></Star>
           
           {makeStars((num - 1))}
          </div>
          
        );

And this is the star component

 <NavLink to={props.name}>
      <h1 className="star-label">{props.name}</h1>
      <div className={``}>
        <div className={`starBall ${props.starType}`}></div>
      </div>
    </NavLink>

At the moment I want the user to be able to click on each star and have it lead to a page. I have achieved that with react-router's dynamic routing

  <Route
          exact
          path="/:id"
          render={(props) => <GenerateSystem {...props} />}
        />

the issue is I want the page that is generated from my generateSystem component to have the starType prop passed to it by the star component. I am aware of React's one way data flow and I think that might be the issue. How can I pass prop data from an auto generated component to another auto generated component?

My full code is viewable here. The components I'm talking about are in the interstellar-view and systems folder.



Solution 1:[1]

since you are passing name through URL params so passing starType using query params is an easy option.

So URL would look like this www.example.com/123?starType=red-giant

In your star.jsx, make a modification like this

<NavLink to={`/${props.name}?starType=${props.starType}`}>
 ...
</NavLink>

In your App.js, make a modification like this

<Switch >
    <Route exact path="/:id"  component={GenerateSystem} />
    <Route exact path="/sol" component={SolSystem} />
    <Route exact path="/" component={Interstellar} />
</Switch>

(We do not need to render and pass props since we can use useParams in GenerateSystem.js)

In your GenerateSystem.js, make a modification like this

import React from "react";
import { Link, useLocation, useParams } from "react-router-dom";

function useQuery() {
  return new URLSearchParams(useLocation().search);
}

export const GenerateSystem = (props) => {
    const {name} = useParams();
    const query = useQuery();
    const starType = query.get('starType')

    return(<div className={starType}>System <p>{name}</p></div>)
}

Refs:

https://reactrouter.com/web/api/Hooks/useparams

https://reactrouter.com/web/example/query-parameters

EDIT:

You can use Redux-store/Context-API to have a global store, so that name and starType can be stored globally and can be accessed in different components

Solution 2:[2]

More Use-cases Example -> for other people that came here:

As in React-Router-Dom V6-> there is no render method any more, See Why does have an element prop instead of render or component?

We mentioned this in the migration guide from v5 to v6, but it's worth repeating here. In React Router v6 we switched from using v5's and APIs to . Why is that?...

So I needed another way of dynamically rendering all routes for the Router, with a pre declared array with all routes:

const routingList = [{title: 'Home', search: '/', component: Home, icon: 'fa-home'},{...}]

<Routes>
    {
      routingList.map((routing) => {
       let Child = routing.component;
       return <Route key={routing.search} path={routing.search} element={<Child {...routing.compProps} />} />;
     })
    }
    <Route path="*" element={<Notfound />} />
</Routes>

(BTW: if you also need the useLocation or the other hooks, and you are using React Class and not React functions, see my answer here:

Component with router props - For: Hooks can only be called inside of the body of a function component )

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2