What is the difference between <Route component={MyComponent} /> and <Route>{MyComponent}<Route />? - reactjs

I have seen 2 ways to define routes in React:
<Route path="/" component={MyComponent} />
and
<Route path="/">{MyComponent}<Route />
Can anyone explain me the difference between the two?

You should not really use the:
<Route path="/">{MyComponent}<Route />
variant. It will only work if the component is a Function component(if you try to put a class component you will get an error), and only if the component doesn't have hooks inside. Route type definition states that in props.children it recieves a render function that returns a React.ReactNode based on route props (history, match parameters, ...) or directly a React.ReactNode. So you should really use it like this:
<Route path="/"><MyComponent /><Route />
Or if your component need route props (and this is then the same as ):
<Route path="/">{(props) => <MyComponent {...props} />}<Route />
Hope this helps.

Related

Is it possible to render different components depending on a url params value within the same url in react-router-dom?

So basically title is my question. Is it possible to achieve something like this with only url paramater change:
<Route path={'/users/:id'} component={()=> UsersPage}/>
<Route path={'/users/:filterOption'} component={()=> UsersList}/>
react-router-dom#5
Yes, absolutely you can. The Router component inclusively matches and renders routes (as opposed to the Switch component that exclusively matches them). This means the Router will render all routes and redirects that are matched by the path prop.
Given path `"/users/someValue":
<Router>
<Route path={'/users/:id'} component={()=> UsersPage}/>
<Route path={'/users/:filterOption'} component={()=> UsersList}/>
</Router>
Both components can be matched and rendered.
Note about Route component prop!
Route render methods
When you use component (instead of render or children) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop.
This means you should not use the component prop if you are providing a function. Instead do one of the following
<Router>
<Route path={'/users/:id'} component={UsersPage}/>
<Route path={'/users/:filterOption'} component={UsersList}/>
</Router>
or
<Router>
<Route path={'/users/:id'} render={()=> <UsersPage />}/>
<Route path={'/users/:filterOption'} render={()=> <UsersList />}/>
</Router>
or
<Router>
<Route path={'/users/:id'}>
<UsersPage />
</Route>
<Route path={'/users/:filterOption'}>
<UsersList />
</Route>
</Router>
react-router-dom#6
react-router-dom#6 now always exactly matches and uses a path ranking/scoring system and '/users/:id' and '/users/:filterOption' have the same specificity and will have the same score. There's nothing to disambiguate between them. Instead you'll rendering a single route and need to use the useParams hook to read the route param, either in a wrapper component or directly in the routed components.
Example with wrapper component.
const UserWrapper = () => {
const { id } = useParams();
return (
<>
<UsersPage id={id} />
<UsersList filterOption={id} />
</>
);
};
...
<Router>
<Routes>
<Route path={'/users/:id'} element={<UserWrapper />} />
...
</Routes>
</Router>
Yes, we can do that in react-router, Just check this article, it has best example for Dynamic URL Parameters.

How to pass data from functional component to class component in reactjs?

I want to pass data from my App.js file to a sub class component.I have tried with props,but its not workng at all
const org = 'Organization Dashboard'
const remotes = 'FromAdmin';
const DashboardContainer = ()=>(
<Sidebar org={org}>
<div className="App">
<Route path='/dashboard' component={Dashboard}/>
<Route path='/mytab' component={MyTab}/>
<Route path='/team' component={MyTeam}/>
<Route path='/settings' component={Settings}/>
<Route path='/logout' component={Logout}/>
<Route path='/team-settings/:param1' component={TeamSettings}/>
**<Route remotes='remotes' path='/user-settings/:param1' component={MyTab}/>**
</div>
</Sidebar>
)
I want to pass data in MyTab class component, when i use this.props in myTab , its showing undefined
Help will be appreciated
I assume you're trying to pass remotes='remotes' to MyTab. Components rendered by a Route are passed only the route props, but you can use an anonymous inner function to slip in extra props. Don't forget to pass on the route props if you need them!
<Route
path='/user-settings/:param1'
component={routeProps => <MyTab {...routeProps} remotes='remotes' />}
/>
You can override the component. By default, component accepts a class-based or function-based component. But you can override the component. Not only data you can pass functions as well. But you should not do this. Use redux to achieve this kind of thing. If it is static data then you can pass this way. But id it is dynamic data then use redux instead.
<Route
path = '/myTab'
component = {(props) => <MyTab {...props} data={data}/>}
/>

React Router difference between component with and without function

const PATH = BASE + '/' + id;
<Route path="PATH" render={PageContainer} /> (DOESN'T WORK for the case below)
<Route path="PATH" component={PageContainer} /> (DOESN'T WORK for the case below)
<Route path="PATH" component={ () => <PageContainer /> } /> (WORKS)
Steps:
1) go to the page BASE/1
2) go back to BASE
3) go to BASE/2
PageContainer connects to the store and passes props to Page.
Why the second approach works, but the first one not?
Update: <Route path="PATH" render={PageContainer} /> (DOESN'T WORK for the case below)
Try accessing it like this:
<Route path="PATH" component={PageContainer} />
There is a difference between component and render props. You can find the answer here:
react router difference between component and render
render — A function that returns a React element. It will be called when the path matches. This is similar to component, but is useful for inline rendering and passing extra props to the element.
PageContainer is a component so should called but not like PageContainer
Change
<Route path="PATH" render={PageContainer} />
To
<Route path="PATH" render={<PageContainer />} />
In your case I recommend you to use component prop instead of render
<Route path="PATH" component={<PageContainer />} />

How to pass props to react-router 4 components?

Id like to use my app entry point as a global state store. Passing info down to children as props.
Using react-router 4, how can I send prop data down to the rendered components. In a similar fashion to this:
<Route Path=“/someplace” component={someComponent} extra-prop-data={dataPassedToSomeComponent} />
I’ve seen some janky workarounds for older versions of react-router, that appear to be deprecated.
What is the correct way of doing this in v4?
You can pass in a function to the render prop instead of passing in the component directly to the component prop.
<Route path="/someplace" render={() => <SomeComponent props={} />} />
You can read more here.
And to add to the above answer, if you want the routing properties accessible to the component you need to include those. Now when the router activates "SomeComponent", the component will get all the routing props plus the extra param(s) - in this example "param".
<Route path='/someplace' component={(props) => <SomeComponent param="yo" {...props}/>} />
Technically there is 2 ways to do it.
The first one (not the most efficient) is to pass an inline function to the component prop:
<Route
path=“/someplace”
component={(props) => (
<SomeComponent {...props} extra-prop-data={ dataPassedToSomeComponent } />
) />
The second one is the best solution. To prevent create a new component on every render like on the first exemple, we pass the same inline function but this time to the render prop:
<Route
path=“/someplace”
render={(props) => (
<SomeComponent {...props} extra-prop-data={ dataPassedToSomeComponent } />
) />

How to Pass Data Through My React-Router with ReactJS?

I have the following JSON object...
{ name: "Jessie" }
And I want to be able to pass it through my Router so that it can be displayed on my pages. For example, this is my root page...
StaticPage.jsx
export default class StaticPage extends React.Component {
render() {
return (
<div>
<Router history={hashHistory}>
<Route path='/' component={Search} />
<Route path='/favorites' component={Favorites} />
</Router>
</div>
);
}
}
So passing this data to Search, I would imagine might look something like this...
<Route path='/' component={Search} name = {this.props.name}/>
However, nothing gets rendered when I do that. I have researched this quite a bit and understand, from what I've read, that you cannot pass objects through the Router. It's very odd bc Router looks like a traditional React component but does not function as such. None of the explanations of a work around seem clear to me. Could anyone provide me with an example using this code? I am using react-router 3.0. There didn't seem to be any magical solution with 4.0 so I figured I'd ask before upgrading. Thanks!
It's because the component prop of <Route> only renders the component with route props, not your supplied props.
You can use the render or component prop on a <Route> in React Router v4 to pass a function which returns a <Search> element that explicitly passes the name:
<Route path="/" render={() => <Search name={this.props.name} />} />
Or with component:
<Route path="/" component={() => <Search name={this.props.name} />} />
But you should prefer render or else you'll have lots of remounting. If you still plan to use route props, you can also do:
render={routeProps => <Search name={this.props.name} {...routeProps} />}
A whole different approach, one more elegant in my opinion is to use route params and pass the name directly through the URL:
<Route path="/:name" component={Search} />
When you navigate to /Bob, you can access this.props.match.params.name which'll give you "Bob".
It is not a good practice to pass the object data via the routes directly. It is recommended to pass a param such as name or id in this way:
<Route path='/favorites/:name' component={Favorites} />
And retrieve it from your request in the destination.
This is a duplicate issue: Pass object through Link in react router

Resources