Pass props to components react-router 1.0.x - javascript

I'm using react-router 1.0.2. I have a component Catalog representing a catalog of products, I don't want to write a different Catalog for each different product but to reuse the existing one and to pass the productType as prop from the router. How am I supposed to do it with this version of react-router? So far I have tried this without sucess... Thank you
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="phones" component={Catalog} productType="phones"/>
<Route path="about" component={About}/>
<Route path="login" component={Login}/>
</Route>
</Router>
</Provider>,
document.getElementById('main')
);

I would leave your routes as generic as possible, which is what I think you're trying to achieve. To do this, you could look at the current path from within your Catalog component and depending on what it is, render a different child element. Suppose you have a Product component, you could pass the product type to that.
So if you had route:
<Route path="catalog/:productType" component={Catalog}/>
You could do this:
class Catalog extends React.Component {
render() {
let productType = this.props.params.productType;
return (
<div className="catalog">
<Product type={productType}/>
</div>
);
}
}

Related

Should I be using functions instead of classes for pages in ReactJS?

I've noticed React Router DOM (v6) is now using functions in their help guides in regards to pages instead of using classes.
Previously used classes like so:
export class Login extends React.Component {
render() {
return <p>test</p>
}
}
However, after trying the latest version of React Router DOM I would receive an empty page for the navigation route.
import {Login} from "./js/components/Auth/Login";
function App() {
return <h2>Test</h2>
}
if (document.getElementById('app')) {
ReactDOM.render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/login" component={() => <Login />} />
</Routes>
</BrowserRouter>, document.getElementById('app'))
}
App works fine ('/' route), but /login returns an empty page with no error..
Login refers to a class that uses render() and returns <p>test</p>
Am I doing something incorrectly? Are libraries leaning towards functions instead of class components?
This guide seems to be only using functions for components.
https://reactrouter.com/docs/en/v6/getting-started/tutorial
Class vs Function components is irrelevant in RRDv6, they simply render React components specified as JSX, not as a reference to a component, and not as a function returning JSX. There is also no render or component props, the Route components now use only element to render the route components.
<Routes>
<Route path="/" element={<App />} />
<Route path="/login" element={<Login />} />
</Routes>

Pass prop value down from login component to routes component

I have a login form setup using and one particular value props.values.userType I need to pass down via props to my index.js file where I render all my routes.
So in my <Login> component I have a <RadioButtonGroup> that renders the 3 types of users available
<RadioButtonGroup
id="userType"
label="User Type"
value={values.userType}
error={errors.userType}
touched={touched.userType}
onBlur={handleBlur}
>
From here the userType exists in formik as props.values.userType
I want to pass this prop value down to my index.js file that renders all my routes.
index.js below
const Routes = () => (
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/login" component={FormikLoginForm} />
<PrivateRoute exact path="/admin" component={AdminPage} />
<Route path="/admin/change-password" component={ChangePassword} />
</Switch>
</Router>
);
How can I achieve this?
codesandbox here
Instead of using component as a prop for each <Route />, you can use the render prop to pass props into the component you want to render on that route.
For example in your case, if your component was called Login:
<Route
path='/login'
render={(props) => <Login {...props} userType={props.values.userType} />}
/>
Or something similar depending on your use case.

Render child component over parent

I need to render component with another route but this component must not cover all page. For example, I clicked on some question from stackoverflow list, and than I will receive animate from right to left modal, and I need to change route also
React router (I am using V4)
export default (
<Switch>
<App>
<Route exact={true} path="/" component={App} />
<Route exact={true} path="/product/:id" component={Product}/>
</App>
</Switch>
);
My product container looks like
export default function productContainer(ChildComponent) {
class ProductContainer extends Component {
render = () => {
return <ChildComponent/>
}
}
return ProductContainer;
}
And my product component
class Product extends Component {
render = () => {
return ("")
}
}
export default productContainer(Product);
When I emulate situation, which I describe above, my page fully rerendred and I don't see my App component Page
Have any idea, how I can resolve this issue?
People have asked how to render a modal as a route before in react-router without re-rendering (can't find the discussion right now). Essentially with react-router this is not possible. Each route change causes a re-render. That said, you can do what you want by nesting your routes.
Each component can return routes, so by using composition you can choose where to render any route.
For instance,
export default (
<Switch>
<App>
<Route path="/" component={App} />
</App>
</Switch>
);
Inside <App /> -
render() {
return (
<Something>
<PageHeader />
<Switch>
<Route path="/product/:id" component={Product}/>
</Switch>
</Something>
);
}
So you can see, if you were to add your routes inside the App component, they can all share a common page layout.
Remember: Any component can return multiple routes or just a single one inside a Switch! Switch will only render the first route that matches.
Also Remember: Routes inside a switch must be a direct child, you can't have Switch -> App -> Route, it must always be a direct child like Switch -> Route
Use render property instead of component in Route.
<Route exact={true} path="/" render={() => (
<div>
<App />
<Route exact={true} path="/product/:id" component={Product}/>
</div>
)} />

React Router - Stay at the same page after refresh

I'm learning React. I have page with 4 subpages and i use React Router to go through those pages. Everything works fine except for reloading page. When i go from page "home" to "about" or other it's ok, but when i refresh page then it render again page "about" for a second and then it change page to home (home is default/first page).I want it to stay at that page which is currently rendered, not go back to home after every refresh.
There is my code in index.js file where i render whole app and use router:
<Provider store={store}>
<Router path="/" history={browserHistory}>
<Route path="/home" component={App}>
<Route path="/" component={Home}/>
<Route path="/allhotels" component={AllHotels}/>
<Route path="/addhotel" component={AddHotel} />
<Route path="/about" component={About} />
</Route>
<Route path="/signin" component={SignIn} />
<Route path="/signup" component={SignUp} />
</Router>
</Provider>, document.getElementById('root')
In "App" i have Navigation and there i render rest of conent from Home, AllHotels etc.
There is code from App.jsx
class App extends Component {
render() {
return (
<div className="app-comp">
<Navigation />
<div> {this.props.children}</div>
</div>
)
}
}
I also attach gif which shows my problem.
https://gifyu.com/image/boMp
In backend i use Firebase if it's important.
Thanks in advance.
I found the reason of my problem. I use also Firebase in my project and it causes the problem.
Thanks guys for help.
EDIT ======================================================================
Mabye I will write how I've fixed my problem and what was the reason of it.
So i was checking if user is logged in or not in auth method. And there if user was authorized I was pushing / to browserHistory.
It was mistake because every refresh method was executing and then also redirection was called as well.
Solution is just to check if during executing auth method I'm on Signin page or not. If it is Signin page then I'm pushing / to browserHistory but if not then just don't push anything.
firebaseApp.auth().onAuthStateChanged(user => {
if (user) {
let currentPathname = browserHistory.getCurrentLocation().pathname;
if( currentPathname === "/" || currentPathname === "/signin"){
browserHistory.push('/');
}
const { email } = user;
store.dispatch(logUser(email));
}
else {
browserHistory.replace('/signin');
}
})
I know that it's not pretty solution but it works and it was only home project which was created to learn react. (btw this project is using old react router 3.0 so probalby now using browserHistory is deprecated)
Check that firebase does not interfares with the client side routes :P
You can use Index routes to achieve this.
You have your navigation i.e the layout of all pages in your app component so make it the root route.
Then you want your home route to be your default route so make it your Index route.
You need to import IndexRoute from react-router package (from which you import Route).
Add this-
import { Router, Route, IndexRoute } from 'react-router';
and then make your routes like below.
Use this-
<Provider store={store}>
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home} />
<Route path="/home" component={Home}/>
<Route path="/allhotels" component={AllHotels}/>
<Route path="/addhotel" component={AddHotel} />
<Route path="/about" component={About} />
</Route>
<Route path="/signin" component={SignIn} />
<Route path="/signup" component={SignUp} />
</Router>
</Provider>, document.getElementById('root')
it's a Server-side vs Client-side issue
check the following thread, it might give you some insights.. React-router urls don't work when refreshing or writting manually
Below example you can refer for :
React Router Navigation
Browser Refresh Issue.
Browser Back Button Issue.
Please make sure you have installed react-router-dom
If not installed. Use this command to install npm i react-router-dom
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Page1 from "./Page1";
import Page2 from "./Page2";
const rootElement = document.getElementById("root");
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route exact path="/" component={Page1} />
<Route path="/page2" component={Page2} />
</Switch>
</BrowserRouter>,
rootElement
);
Page1.js
import React from "react";
import {Link } from "react-router-dom";
function Page1() {
return (
<div>
<p>
This is the first page.
<br />
Click on the button below.
</p>
<Link to="/page2"><button>
Go to Page 2
</button>
</Link>
</div>
);
}
export default Page1;
Page2.js
import React from "react";
function Page2() {
return (
<div>
<p>This is the second page.</p>
</div>
);
}
export default Page2;
Add into your webpack.config.js this option
devServer: {
historyApiFallback: true
},
Route tag returns the first matching component.
I think you have interchanged the paths of home and app component.
try this.
<Provider store={store}>
<Router path="/" history={browserHistory}>
<Route path="/" component={App}>
<Route path="/home" component={Home}/>
<Route path="/allhotels" component={AllHotels}/>
<Route path="/addhotel" component={AddHotel} />
<Route path="/about" component={About} />
</Route>
<Route path="/signin" component={SignIn} />
<Route path="/signup" component={SignUp} />
</Router>
</Provider>, document.getElementById('root')

How do I pass Redux props to a separate component in a different Route with React Router v4?

I'm creating a real time chat app with react, react router v4 and redux. The problem is that, as you may know, react router v4 changes a lot of stuff and nesting routes is not working for me.
So I have this code with a nested route that is not working:
<Route path='/' component={App}>
<Route path="/user" component={AddUser}/>
</Route>
It's giving me this error Warning: You should not use <Route component> and <Route children> in the same route; <Route children> will be ignored.
Where component={App}, in the first <Route path='/' is a redux connect:
const App = connect(mapStateToProps, mapDispatchToProps)(Header)
So my component App has all the the props I need. All works fine except by the fact that I need to pass those props from App to the nested route component AddUser.
How do I pass the redux props to a separate component in a different Route?
With react-router v4 when we need nested routes, we don't nest Routes. Instead, we put them inside nested components. You can read about this more here: Nested routes with react router v4
In your case, you can put your "/user" route inside the App component and then use render instead of component. So you can pass your App props to AddUser as usual.
<Route path='/' component={App}/>
App.js
class App extends Component{
//...
render(){
return(
//....
<Route path="/user"
render={() => <AddUser myProp={this.props.myAppProp}/>}/>
//....
)
}
}
I found a solution reading this blog post: https://medium.com/#5XvYrLT7/react-server-side-rendering-with-react-router-3-x-74cf87919b3
With react-router v4 you don’t do this any more, don’t nest :
<Route component={App}>
<Route component={Index} />
<Route component={About} />
</Route>
You do it like this now. App embeds your routes as-is:
<App>
<Switch>
<Route exact path="/" component={Index} />
<Route path="/about" component={About} />
</Switch>
</App>

Categories

Resources