Search code examples
reactjsapireact-routerreact-router-domreact-props

Passing props through Link to a child component to complete the url to make an api call


I have a father component (which is a child of HousesGallery and receiving props to display api data), but now I want to display HouseDetail component as a place to show details about the house where you clicked. The api needs the name of the house so I'm trying to pass the name through props via Link and I don't know if I'm missing something in the Route or somewhere else.

App component where the Route is:

export default function App() {
  return (
      <div className="got-font">
          <Router>
              <div>
                <Menu/>
              </div>
              <Switch>
                  <Route path="/detallecasa/:name">
                      <HouseDetail/>
                  </Route>
                  <Route path="/personajes">
                      <CharactersGallery/>
                  </Route>
                  <Route path="/casas">
                      <HousesGallery/>
                  </Route>
                  <Route path="/cronologia">
                      <Chronology/>
                  </Route>
                  <Route path="/">
                      <HomePage/>
                  </Route>
              </Switch>
          </Router>
      </div>
  );
}

Father component:

export default function HouseComponent(props) {

    return (
        <div className="container">
            <div className="row">
                    {props.info.map((item, i) =>
                    item.logoURL ?
                        <Link to={{pathname: `/detallecasa/${item.name}`, query: {housename: item.name}}}
                              key={i} className="col-lg-2 col-md-4 col-sm-12 c-houses_div">
                            <figure className="c-houses_div_figure" key={i}>
                                <img className="c-houses_div_figure_img" src={item.logoURL} alt=""/>
                                <figcaption>
                                    <h3>{item.name}</h3>
                                </figcaption>
                            </figure>
                        </Link> : null
                    )}
            </div>
        </div>
    );
}

And the child component:

export default function HouseDetail(props) {
    const [houseDetail, setHouseDetail] = useState([]);

    useEffect(() => {
        axios.get(process.env.REACT_APP_BACK_URL + "houses/" + props.match.params.housename)
            .then(res => {
                console.log(res.data)
                setHouseDetail(res.data);
            })
    }, [])

    return (
        <div className="">
            <div className="container">
                <div className="row">
                    {houseDetail.map((item, i) =>
                        <div key={i} className="">
                            <figure className="" key={i}>
                                <img className="" src={item.logoURL} alt=""/>
                                <figcaption>
                                    <h3>{item.name}</h3>
                                </figcaption>
                            </figure>
                        </div>
                    )}
                </div>
            </div>
        </div>
    );
}

Solution

  • The Link's to prop object doesn't take a query property, but you can pass additional data in route state

    <Link
      to={{
        pathname: `/detallecasa/${item.name}`,
        state: { housename: item.name }, // <-- Pass route state, if you wanted to
      }}
      ... // other props, etc..
    >
      ...
    </Link>
    

    This issue is more about how you are trying to reference the route's match params in the rendered component.

    The access the route match param based on what it is named in the Route's path, i.e. name.

    <Route path="/detallecasa/:name"> // <-- match param is `name`
      <HouseDetail/>
    </Route>
    

    Access correctly, i.e. props.match.params.name.

    useEffect(() => {
      axios.get(process.env.REACT_APP_BACK_URL + "houses/" + props.match.params.name)
        .then(res => {
          console.log(res.data)
          setHouseDetail(res.data);
        })
    }, []);