react router private route implementation is path props passed or not? - javascript

Hello everyone this is more of a request asking review on my understanding of private route implementation in react.js rather than a question. Many implementations of private routes with authentication seem to have this same code posted
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={(props) => (
fakeAuth.isAuthenticated === true
? <Component {...props} />
: <Redirect to='/login' />
)} />
)
now as far as I know the 3 dots is the spread operator which basically assigns the passed object . Further SO answer also corroborates it What do these three dots in React do? especially the answer from Mehdi Raash . Now my understanding is that this basically means that the 'path' prop is also passed in the ...rest object just like
<Route path={rest.path} render={(props) => (
fakeAuth.isAuthenticated === true
? <Component {...props} />
: <Redirect to='/login' />
)} />
but recently i have came across this post https://ui.dev/react-router-v4-protected-routes-authentication/
and this line just doesn't make sense to me
A few notes on the above code. With Route, if a path isn’t supplied, then that Route will always match. So in the case above, because we didn’t supply a path prop, the Route will always match which means the render prop will always be called.
So I just want to know whether this statement is correct and path props isn't being passed in the private route implementation and if so then what is this {...rest} doing in the Route.
Note: No offence for the author behind the article i just want my understanding stand corrected if I am wrong

The spread operator basically puts all remaining properties into a new object called rest in your case. Let's say that PrivateRoute was initiated like this:
<PrivateRoute component={Home} path="/protected" secure={false} />
component was desctructured and renamed to Component in your example. This means that rest looks like this:
rest = {
path: "/protected",
secure: false
}
What happens next is that the rest object is spreaded into the Route. So this:
<Route {...rest} render={(props) => ()} />
is the same as this:
<Route path={res.path} secure={res.secure} render={(props) => ()} />
or this:
<Route path="/protected" secure={false} render={(props) => ()} />
By the way, the props in the render() function only contain three props and they come from the Router:
match
location
history

Related

React router rendering

I have a piece of code that I can not understand. Any explanation is appreciated. My question is what (props) actually is doing here and where it comes from? If I take "props" out, my code is not working.
<Route
exact
path='/'
render={(props) =>
!isAuthenticated ? (
<Landing {...props} />
) : (
<Redirect to='/admin' />
)
}
/>
Route is a component of react-router , which matches the url and routes , The code you have given is used for Authentication to redirect user if he is not Authorized ,whatever that is passed from parent has to be passed to the children in this case , the reason they are passing props is to pass the properties of React Router which includes things like history,location and etc. A simple console.log will show you what it is passing and why it is required
Refer to Image below to see what all is getting passed

When a URL has a parameter, why do we place the child component inside an attribute

I am currently watching a tutorial on React.
Why do we place the <Person /> inside the children attribute instead of between the <Route></Route>?
Why is <Person /> wrapped between {}. I thought that the {} inside a jsx expression signals that everything inside of it are javascript expressions. But <Person /> is not a javascript expression?
Why do we place the <Person /> inside the children attribute instead of between the <Route></Route>?
They are 2 ways of using children in react component. I'm not sure why the mentor used both of them. Maybe he/she just showed you 2 ways of using children.
Why is <Person /> wrapped between {}. I thought that the {} inside a jsx expression signals that everything inside of it are javascript expressions. But is not a javascript expression?
Route has a prop children and it receives a function component Person, so you should wrap it by {}. Read doc here.
const Person = () => {
return <p>Person</p>;
};
const App = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" children={<Person />} />
{/* You can rewrite it as below */}
<Route exact path="/" children={() => { return <p>Person</p>; }} />
</Switch>
</BrowserRouter>
);
};
codesandbox

Why aren't {...props} necessary when passing them to a component in a router in React?

I've started learning React recently and when I was following a course I stumbled upon something that confused me a lot. I decided to try it out separately to understand it and I don't get it.
I've looked it up and when you use a Route Tag in React, you do it like this:
<Route path="/" component={Component} />
But when you want to pass props, the syntax is the following:
<Route path='/dashboard' render={(props) => (
<Dashboard {...props} isAuthed={true} />
)}
/>
Which at first confused me, but then I got it. When testing, I did the following:
<Route path="/" render={() => (
<PropDrilling user={"Someone"} />
)}>
When I test this in the component, console.logging this.props, it works and I don't know why.
Thanks in advance!
React router uses React's render props where react router uses match, location and history. So, when you don't provide props in the render function, it will still be able to show you react component props. But it would not include match, location and history props provided by react router. To use them, you must provide props parameter in the render function.
Using an analogy, consider
function test(obj) {
console.log(obj);
}
test({a : 1});
function test() {
console.log({a : 1});
}
test();
These two functions log the same result, but one has no information about the data passed to console.log, while the other does.
Similarily, {...props} means you are forwarding the props received as a function parameter to a component, irrespective of what the value of props is.
Taking the example of <Route path="/" component={Component} />, you could write it like that :
const myProps = {
path: "/",
component: <YourComponent />
}
<Route {...myProps} />
Consider every props passed to a component as a key in an object. Here is a small repro on Stackblitz to show you how it works.

Why pass {...props} in a React Route?

I'm using the route below just because it was the code I found on the web:
<Route exact path="/test" render={(props) => <Test {...props} msg={ "abc" } /> } />
I know the {...props} denotes multiple arguments but I can't understand why I need it at all because the code below also works just fine and props.msg is available in Test expected
<Route exact path="/test" render={() => <Test msg={ "abc" } /> } />
So what does {...props} actually do when passed in during render?
From the documentation:
The render prop function has access to all the same route props (match, location and history) as the component render prop.
If Test is not using any of these then you don't have to pass them.
For your use case, your second code snippet is sufficient and will work just fine.
Spreading the props into the child component like
<Route exact path="/test" render={(props) => <Test {...props} msg={ "abc" } /> } />
makes sense if you want to pass properties to the child component that you are not handling yourself but receiving from another source like the Route-Component itself (in particular the route props "match", "location" and "history").
Keep in mind you can have parameters in your route, ex:
/users/:username
Those props will allow you to access it. In your case, you probably don't need it but you're better to always include them so it's consistent.
https://reacttraining.com/react-router/web/api/Route/route-props
more doc about the 3 props that are provided :
match https://reacttraining.com/react-router/web/api/match
location https://reacttraining.com/react-router/web/api/location
history https://reacttraining.com/react-router/web/api/history

router changed but component does not rerender

I'm using react-router v4 and redux. I have a react-router event like so
//src/App/components/common/Notifications
onCommentClick = (id) => {
this.props.history.push(`/dashboard/${id}`)
}
It will change the browser url, my route is setup correctly I guess
//src/App/containers/dashboard/user/NotificationDetail
renderUserRoute() {
return (
<Switch>
<Route exact path="/dashboard" component={UserAreaGuarded} />
<Route exact path="/dashboard/:id" component={NotificationDetail} />
</Switch>
)
}
but the problem is redux doesn't seem to rerender my container component, I need to refresh to get the right content.
I created a repo just to demo this issue https://github.com/thian4/hoc-redux, been stuck for so long for this, couldn't find any clue why it doesn't rerender.
The problem was not with the router, the NotificationDetail component invokes fetchNotification only in componentDidMount. As you are rendering the route components with the Route component prop, the NotificationDetail route component is mounted only once and then merely updated on every re-render.
There are two ways to fix this...
In NotificationDetail, do the fetchNotification stuff in componentDidUpdate instead of componentdidMount, simply rename the method. This approach is better.
Use a stateless component as the value of component prop in dashboard\index.js:
renderUserRoute() {
return (
<Switch>
<Route exact path="/dashboard" component={UserAreaGuarded} />
<Route exact
path="/dashboard/:id"
component={props => <NotificationDetail {...props} />} />
</Switch>
)
}
This will make React-Router render a new route component every time the route changes. Obviously this has performance issues over #1.
Unrelated to this, please add a key={i} on this line in Notification.js to fix the dreaded Each child in an array or iterator should have a unique "key" prop. warning.
Hope this helps.

Categories

Resources