Search code examples
reactjsreact-routerreact-propsreact-link

Is it possible to pass props by match in React Link


I am passing props to the same component in two different ways.

Once by Route path:-

<Route path="/CreateProfile/:title" exact component={ProfileForm} />

Another by Link as:

<Table.Cell><Link to={{  // it will land to the same component ProfileForm
pathname:  "/EditProfile",
props: {
profile : profile,
title: "Edit Profile" 
}
}} >Edit Profile</Link></Table.Cell>

In my ProfileForm, I tried to read props as:-

useEffect(() => {

  if(props.match.params.title){ // it gives no error. 
    setTitle(props.match.params.title);
  }else if(props.location.props.title){ // gives error .props.title undefiened 
    setTitle(props.location.props.title);
  }
  // if(props.match.params.profile){
  //   setProfile(props.location.state.profile)
  // }
  if(props.location.props.profile){
    setProfile(props.location.props.profile)
    console.log("profile: "+props.location.props.profile)
  }
}

else if(props.location.props.title) gives an error when it comes from the Router. It is expected because I set props by Link. I noticed props.match.params.title never gives any error whether it is set or not. So I wish to pass props by the match from Link so that both Route and Link works properly. Is it possible to pass props by match? Or how do I solve this issue?


Solution

  • You can pass data via the pathname (URL), i.e. via url match or query parameters, or via route state.

    Link to-object

    An object that can have any of the following properties:

    • pathname: A string representing the path to link to.
    • search: A string representation of query parameters.
    • hash: A hash to put in the URL, e.g. #a-hash.
    • state: State to persist to the location.

    You clearly have your route setup for the pathname variant with a route param of title.

    "/CreateProfile/:title"
    

    You should simply construct your link to have the correct title value built into it.

    <Link to={{ pathname: "/CreateProfile/<some title value>" }} >
      Create Profile
    </Link>
    

    From here you need only access the route's match.params.title as you've correctly done.

    Now, in the case of the edit profile route, "/EditProfile" there is, OFC, no route match param (and no query parameters), so the correct way is to use route state.

    <Link
      to={{
        pathname: "/EditProfile",
        state: {
          profile,
          title: 'Edit Title',
        },
      }}
    >
      Edit Profile
    </Link>
    

    And correctly access route state from the history object

    useEffect(() => {
      const { history, match } = props;
    
      if (match.params.title) { 
        setTitle(match.params.title);
      } else if (history.location.state.title){
        setTitle(history.location.state.title);
      }
    
      if (history.location.state.profile) {
        setProfile(history.location.state.profile)
        console.log("profile: ", history.location.state.profile)
      }
    }
    

    Word of advice about the route state however, the object path isn't always guaranteed to exist (i.e. be defined) from props.history.location to the ultimate value you are accessing, so guard are necessary to prevent "access blah of undefined" errors.

     // state may not be defined depending on which route the app took to get to the page
    history.location.state && history.location.state.title