Home > OS >  Private route and reading Params - React Django
Private route and reading Params - React Django

Time:01-25

I am building a Django React app following a tutorial where they use react-router v5, and I use the v6.2.1 (code is here : https://github.com/linkedweb/realest_estate/blob/main/src/containers/ListingDetail.js).

I want to have a PrivateRoute for authenticated user rendering details of a product. I tried to adapt the code, according to this post especially (React - TypeError: Cannot read properties of undefined (reading 'params')), but I cannot make it work and I get:

"Uncaught TypeError: Cannot read properties of undefined (reading 'params')"

I tried many variants, but this is what I believe to be the closest to the right way :

App.js

const App = () => (
  <Provider store={store}>
    <Router>
      <Layout >
        <Routes>
          <Route exact path='/' element={<Home />} />
          ...
          <Route exact path='/listings' element={<Listings/>} />
          <Route path='/listings/:id' element={<PrivateRoute />}>
            <Route path='' element= {<ListingDetail />}/>
          </Route> 
          <Route path="*" element={<NotFound />} /> 
        </Routes>
      </Layout>
    </Router>
  </Provider>)

PrivateRoute

const PrivateRoute = ({ auth: {isAuthenticated, loading }, ...rest  }) => {
    return (!isAuthenticated && !loading) ? (<Navigate to='/login' />) : (<Outlet {...rest}/>)}
    
PrivateRoute.propTypes = {
    auth: PropTypes.object.isRequired};

const mapStateToProps = state => ({
    auth: state.auth});

export default connect(mapStateToProps)(PrivateRoute);

Listing Details

const ListingDetail = (props) => {
    const [listing, setListing] = useState({});

    useEffect(() => {
        const slug = props.match.params.id;

        const config = {
            headers: {
                'Authorization': `Bearer ${localStorage.getItem('token')}`}};

        axios.get(`http://localhost:8000/api/listings/${slug}`, config)
        .then(res => {
            setListing(res.data);
        })
        .catch(err => { }); });

    return (
        <div className='listingdetail'>
            <p>{listing.title}</p>
        </div>
    );};

export default ListingDetail;

I tried to change 'const slug = props.match.params.id;' to 'const { slug } = useParams();', even outside the useEffect, but it didn't work !

What can I do in order to retrieve the data about the product and display them ?

Have a nice day !

CodePudding user response:

Move the path prop to the Route you are trying to render that you want the routed component to access a route param of (slug).

<Route element={<PrivateRoute />}>
  <Route
    path='/listings/:slug'
    element= {<ListingDetail />}
  />
</Route>

ListingDetail should use the useParams hook to retrieve the slug route param. Access the slug route param outside the useEffect hook and add slug to the useEffect hook's dependency array.

const ListingDetail = () => {
  const { slug } = usePrams();
  const [listing, setListing] = useState({});

  useEffect(() => {
    const config = {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      },
    };

    axios.get(`http://localhost:8000/api/listings/${slug}`, config)
      .then(res => {
        setListing(res.data);
      })
      .catch(err => { });
  }, [slug]);

  return (
    <div className='listingdetail'>
      <p>{listing.title}</p>
    </div>
  );
};
  •  Tags:  
  • Related