admin管理员组

文章数量:1429064

I have a web app which is under development which is just like google drive using firebase. I have this useParams() in Dashboard Screen which is the main page of the App with All the different Folder Routes. So for this screen i have used useParams and now when i console.log(params) it shows an empty object {} and also when i click the button it does not navigate only the URL changes

Github Code :- /

In App.js

import { BrowserRouter, Switch, Route } from 'react-router-dom';
import PrivateRoute from './Components/Route/PrivateRoute';
import Dashboard from './Screens/Main/Dashboard';
import ViewProfile from './Screens/Profile/ViewProfile';
import Signup from './Screens/Auth/Signup';
import Login from './Screens/Auth/Login';
import ForgotPassword from './Screens/Auth/ForgotPassword';
function App() {
    return (
        <>
            <div className='App'>
                <div className='main'>
                    <BrowserRouter>
                        <Switch>
                            {/* Drive */}
                            <PrivateRoute exact path='/' ponent={Dashboard} />
                            <PrivateRoute
                                exact
                                path='/folder/:folderId'
                                ponent={Dashboard}
                            />

                            {/* Profile */}
                            <PrivateRoute path='/profile' ponent={ViewProfile} />

                            {/* Auth */}
                            <Route path='/signup' ponent={Signup} />
                            <Route path='/login' ponent={Login} />
                            <Route path='/forgot-password' ponent={ForgotPassword} />
                        </Switch>
                    </BrowserRouter>
                </div>
            </div>
        </>
    );
}

export default App;


In Dashboard.js

import NavBar from '../../Components/Shared/NavBar';
import Container from 'react-bootstrap/Container';
import AddFolderButton from '../../Components/Main/AddFolderButton';
import { useDrive } from '../../services/hooks/useDrive';
import Folder from '../../Components/Main/Folder';
import { useParams } from 'react-router-dom';
export default function Dashboard() {
    const params = useParams();
    console.log(params);
    const { folder, childFolders } = useDrive();
    return (
        <div>
            <NavBar />
            <Container fluid>
                <AddFolderButton currentFolder={folder} />
                {childFolders.length > 0 && (
                    <div className='d-flex flex-wrap'>
                        {childFolders.map(childFolder => (
                            <div
                                key={childFolder.id}
                                className='p-2'
                                style={{ maxWidth: '250px' }}>
                                <Folder folder={childFolder} />
                            </div>
                        ))}
                    </div>
                )}
            </Container>
        </div>
    );
}

I have a web app which is under development which is just like google drive using firebase. I have this useParams() in Dashboard Screen which is the main page of the App with All the different Folder Routes. So for this screen i have used useParams and now when i console.log(params) it shows an empty object {} and also when i click the button it does not navigate only the URL changes

Github Code :- https://github./KUSHAD/RDX-Drive/

In App.js

import { BrowserRouter, Switch, Route } from 'react-router-dom';
import PrivateRoute from './Components/Route/PrivateRoute';
import Dashboard from './Screens/Main/Dashboard';
import ViewProfile from './Screens/Profile/ViewProfile';
import Signup from './Screens/Auth/Signup';
import Login from './Screens/Auth/Login';
import ForgotPassword from './Screens/Auth/ForgotPassword';
function App() {
    return (
        <>
            <div className='App'>
                <div className='main'>
                    <BrowserRouter>
                        <Switch>
                            {/* Drive */}
                            <PrivateRoute exact path='/' ponent={Dashboard} />
                            <PrivateRoute
                                exact
                                path='/folder/:folderId'
                                ponent={Dashboard}
                            />

                            {/* Profile */}
                            <PrivateRoute path='/profile' ponent={ViewProfile} />

                            {/* Auth */}
                            <Route path='/signup' ponent={Signup} />
                            <Route path='/login' ponent={Login} />
                            <Route path='/forgot-password' ponent={ForgotPassword} />
                        </Switch>
                    </BrowserRouter>
                </div>
            </div>
        </>
    );
}

export default App;


In Dashboard.js

import NavBar from '../../Components/Shared/NavBar';
import Container from 'react-bootstrap/Container';
import AddFolderButton from '../../Components/Main/AddFolderButton';
import { useDrive } from '../../services/hooks/useDrive';
import Folder from '../../Components/Main/Folder';
import { useParams } from 'react-router-dom';
export default function Dashboard() {
    const params = useParams();
    console.log(params);
    const { folder, childFolders } = useDrive();
    return (
        <div>
            <NavBar />
            <Container fluid>
                <AddFolderButton currentFolder={folder} />
                {childFolders.length > 0 && (
                    <div className='d-flex flex-wrap'>
                        {childFolders.map(childFolder => (
                            <div
                                key={childFolder.id}
                                className='p-2'
                                style={{ maxWidth: '250px' }}>
                                <Folder folder={childFolder} />
                            </div>
                        ))}
                    </div>
                )}
            </Container>
        </div>
    );
}

Share Improve this question asked May 13, 2021 at 8:18 KUSHADKUSHAD 1371 gold badge2 silver badges8 bronze badges 2
  • The dashboard path is "/", there aren't any route match params to list... I'd expect to see an empty object. What buttons are you referring to clicking? There are none in your snippets. Oh, I see, you are trying to also render the Dashboard ponent for other nested routes. Where is the navigation occurring? I assume you have some Link ponents somewhere? – Drew Reese Commented May 13, 2021 at 8:23
  • No the Link ponent is inside the Folder ponent – KUSHAD Commented May 13, 2021 at 10:20
Add a ment  | 

1 Answer 1

Reset to default 4

Issue

After scouring your repo looking for the usual suspect causes for "it does not navigate only the URL changes" I didn't find anything odd like multiple Router ponents, etc. I think the issue is your PrivateRoute ponent isn't passing the props to the Route correctly. You're destructuring a prop called rest and then spread that into the Route, but you don't pass a rest prop to the PrivateRoute

export default function PrivateRoute({ ponent: Component, rest }) { // <-- rest prop
  const { currentUser } = useAuth();
  return (
    <Route
      {...rest} // <-- nothing is spread/passed here
      render={props => {
        return currentUser ? (
          <Component {...props} />
        ) : (
          <Redirect to='/login' />
        );
      }}
    />
  );
}

The routes, these are not passed any prop named rest:

<PrivateRoute exact path='/' ponent={Dashboard} />
<PrivateRoute
  exact
  path='/folder/:folderId'
  ponent={Dashboard}
/>

What I believe to be occurring here is the exact and path props aren't passed to the underlying Route ponent and so the first nested ponent of the Switch is matched and rendered, the "/" one that doesn't have any route params.

Solution

The fix is to spread the rest of the passed props into rest instead of destructuring a named rest prop.

export default function PrivateRoute({ ponent: Component, ...rest }) {
  const { currentUser } = useAuth();
  return (
    <Route
      {...rest}
      render={props => {
        return currentUser ? (
          <Component {...props} />
        ) : (
          <Redirect to='/login' />
        );
      }}
    />
  );
}

An improvement of your private route may be as follows:

export default function PrivateRoute(props) {
  const { currentUser } = useAuth();
  return currentUser ? (
    <Route {...props} />
  ) : (
    <Redirect to='/login' />
  );
}

This checks your user authentication and renders either a Route or Redirect. This pattern allows you to use all the regular Route props so you aren't locked into using the render prop to render the ponent.

本文标签: javascriptreact router use params returns empty objectStack Overflow