I am very new to React, I have got a multipage app with a header bar component that is reused on every page.
class Header extends Component {
render() {
if (!this.props.authenticated) {
return null;
}
return (
<header className="topHeader">
<h1>{this.props.title}</h1>
</header>
);
}
}
export default Header;
I then pass this to App.js (with the title hard coded as "hi" for now):
...return (
<div className="masterContainer">
<Router>
<Header authenticated={this.state.authenticated} title="hi" />
<Switch>
<Route
exact
path="/login"
component={() => (
<LoginPage
updateUser={() => this.loadCurrentlyLoggedInUser()}
/>
)}
/> ...
In the page component itself, I have a blank page for now:
class Messages extends Component {
render() {
return (
<div className="messages">
<h2>Test page - Messages</h2>
<br />
<h2>This is a private page</h2>
<p>
You could only access this page after logged in.
<br />
Changes to the token or user logged out will redirect the user to the
login page.
</p>
<br />
</div>
);
}
}
export default Messages;
Now, I want to set a title on the blank page (as title="Messages") but I only know how to pass one prop to another. But I do not know how to have the prop from the blank page, to App.js, then back to the Header component.
Any tips on how I could do that?
You can pass a method handle to your page component as props. And you Page component can callback the handle component.
There are other advanced ways also like Context API, Redux etc.
App.js
state = { title:'' };
setHeaderTitle = (title) => {
this.setState({ title });
}
...return (
<div className="masterContainer">
<Router>
<Header authenticated={this.state.authenticated} title={this.state.title} />
<Switch>
<Route
exact
path="/login"
component={() => (
<LoginPage setHeaderTitle={this.setHeaderTitle}
updateUser={() => this.loadCurrentlyLoggedInUser()}
/>
)}
/> ...
Page component
class Messages extends Component {
componentDidMount(){
this.props.setHeaderTitle("Page Title");
}
render() {
return (
<div className="messages">
<h2>Test page - Messages</h2>
<br />
<h2>This is a private page</h2>
<p>
You could only access this page after logged in.
<br />
Changes to the token or user logged out will redirect the user to the
login page.
</p>
<br />
</div>
);
}
}
export default Messages;
Related
I use react-router-dom, but when i click on the button, the page is rendered on top of the main one.
I do not need a full-fledged menu with a page transition. I have a button in the component and when I click it, I need to go to the next pageenter image description here
enter image description here
import React from "react"
import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-dom'
import Profile from "../../profile/profile"
import "./UserBlock.scss"
const UserBlock = ({name,city,company}) => {
return (
<Router>
<div className="userBlock">
<div className="userBlock__info">
<div><strong>ФИО: </strong>{name}</div>
<div><strong>Город:</strong> {city}</div>
<div><strong>Компания:</strong> {company}</div>
<button><Link to="/profile">Подробнее</Link></button>
</div>
</div>
<Routes>
<Route path="/App" element={<App/>}/>
<Route path="/profile" element={<Profile/>}/>
</Routes>
</Router>
)
}
export default UserBlock
App.JS
return(
<div className='usersList'>
<div className='usersList__sidebar'>
<span>Сортировка</span>
<SortButton button={sortCity} text="по городу" />
<SortButton button={sortCompany} text="по компании"/>
</div>
<div className="usersList__lists">
<h3>Список пользователей</h3>
{isLoaded ? <img src={preloader} alt="preloader"/> : (
<div className="usersList__items">
{users.map(user => (
<div className="usersList__userCard">
<UserBlock
key={user.id}
name={user.name}
city={user.address.city}
company={user.company.name}/>
</div>
))}
<span>Найдено {count} пользователей</span>
</div>)}
</div>
</div>
)
The <Router> needs to go around everything that you want to change when you navigate.
The picture suggests that you have something like:
<main>
{ users.map(user => <UserBlock {...user} /> }
</main>
in a parent component.
You need to do your routing there and not inside each one of the UserBlocks.
I'm trying to display the details of a clickable object on a new page. I've tried a few examples from React Router Pass Param to Component with limited success.
The only one that "kind of" worked was Alexander Luna's suggestion to access via ID in component. However, while this returns the id number, I can't access any other values, like "title".
I have tried globalStore, however, the error message told me that it isn't defined. I'm not sure that's my best option or not.
Ultimately I want the whole object back as I plan to use context with See 'D' below.
App) I have commented out my previous attempts
class App extends Component {
render() {
return (
<React.Fragment>
<Navbar />
<Switch>
<Route exact path="/" component={ProductList} />
<Route path="/cart" component={Cart} />
<Route exact path="/details/:id" component={Details} />
{/* <Route exact path="/details/:id" render={(props) => <Details globalStore={globalStore}
{...props} /> } /> */}
{/* <Route exact path="/details/:id" render={(props)=>{ <Details id={props.match.params.id}/>}}
/> */}
<Route component={Default} />
Details page I want to render in.
import React, { Component } from "react";
export default class Details extends Component {
render() {
return(
<div>
<h2>{this.props.match.params.id}</h2>
<h2>{this.props.match.params.title}</h2>
</div>
The product page, I'm using this link to click through to details.
xport default class Product extends Component {
render() {
const { id, title, img, price, inCart } = this.props.product;
return (
<ProductWrapper className="col-9 mx-auto col-md-6 col-lg-3 my-3">
<div className="card">
<div className="img-container" onClick={() => console.log('you clicked container')}
>
<Link to={`/details/${ this.props.product.id }`} >
<img src={img} alt="product" className="card-img-top" />
</Link>
D - This is how the original code looked, I want to use the {title} tags but I don't know if I need "value => " etc.
<ProductConsumer>
{value => {
const {
id,
company,
img,
info,
price,
title,
size,
} = value.Product;
return (
<div className="container py-5">
{/* title */}
<div className="row">
<div className="col-10 mx-auto text-center text-slanted text-blue my-5">
<h1>{title}</h1>
</div>
</div>
You need an extra parameter
<Route exact path="/details/:id/:title" component={Details} />
export default class Details extends Component {
render() {
return(
<div>
<h2>{this.props.match.params.id}</h2>
<h2>{this.props.match.params.title}</h2>
</div>
);
}
}
// In Product component
<Link to={`/details/${ this.props.product.id }/${this.props.product.title}`} >
<img src={img} alt="product" className="card-img-top" />
</Link>
Try to read the params in the constructor like this:
constructor(props)
{
super(props)
const { match: { params } } = this.props;
var id = params.id
this.state = {
id : id,
}
}
and then read the id from the state.
If you want to pass the whole object you can send it through the url in base64 like this :
<Link to={`/details/+btoa( this.props.product )} >
<img src={img} alt="product" className="card-img-top" />
</Link>
And recieving it in the constructor like the previous snippet en parse it to string with the function atob() and then to json.
Hello community :) My first Q here.
(There were couple of similar questions but they didn't answer my particular code issue and I tried them to apply but without success.)
So I would like to render the child component in nested route without the parent one showing in the view
See the picture at the end --->
import React from 'react';
import {BrowserRouter, Route, Switch, Link} from "react-router-dom";
import 'bootstrap/dist/css/bootstrap.min.css';
import Routing from "./components/Routings";
export default class Browserrouting extends React.Component {
render () {
return (
<BrowserRouter>
<Routing/>
</BrowserRouter>
)
}
}
Here is the Routing component :
import About from "../views/About";
import HomeBackground from "../views/Background";
import ShelterApp from '../views/ShelterApp';
export default (props) => (
<div className="flexColumn">
<div> <ul className="flexRow center">
<li className="homeLink"><Link className="colorBrown" to="/">Home</Link></li>
<li className="homeLink"><Link className="colorBrown" to="/shelterApp">Shelter App</Link></li>
<li className="homeLink"><Link className="colorBrown" to="/about">About our site and shelter</Link></li>
</ul></div>
<Switch>
<Route exact path="/" component={() => <HomeBackground />} />
<Route path="/about" component={() => <About />} />
<Route path="/shelterApp" component={() => <ShelterApp />} />
</Switch>
</div>
)
And in ShelterApp component I have some text and imported another component which contains the links and nested routes I would like to display without showing the parent component ShelterApp:
class ShelterApp extends React.Component {
render() {
return (
<div className="flex center">
<div className="card center" style={{ "width": "25em", "height":"25em" }}>
<div className="card-body textCenter">
<h5 className="card-title paddingTitle">Welcome to our site</h5>
<h6 className="card-subtitle mb-2 text-muted"> Login or register if it's your first time</h6>
</div>
<LoginRouting match={this.props.match} />
</div>
</div>)
}
}
export default ShelterApp;
and the final child componet with the "lowest" routes in hierarchy :
class LoginRouting extends React.Component {
constructor(props) {
super(props)
this.state = {
users: []
}
}
static propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
};
render() {
const { match, location, history } = this.props;
return (
<div >
<div className="flexRow center">
<Button className={" loginRouting"} type={"button"} bootstrapClass={"btn btn-light"} child={<Link to="/shelterApp/login">Login form</Link>} />
<Button className={" loginRouting"} type={"button"} bootstrapClass={"btn btn-light"} child={<Link to="/shelterApp/register">Register form</Link>} />
</div>
<div>
<Route path="/shelterApp/login" render={() => <Login />} />
<Route path="/shelterApp/register" render={() => <Register />} />
</div>
</div>
)
}
}
export default withRouter( LoginRouting)
enter image description here
IMAGE with the view :
I will be thankful for any advises !
On your ShelterApp component you can create a new state called hideInfo, or something, that tracks if the user clicked on "Login form" or "Register form".
Then you can pass a props to your <LoginRouting> component.
When the user clicks on "Login form" or "Register form" you change this.hideInfo.
<LoginRouting
onShowForm={() => this.setState({ hideInfo: !hideInfo})}
match={this.props.match}
/>
Whenever i click the link component from Topics Component, Topics Component renders again so that the output is displayed twice. The Topics component is nested and have Link component to subtopics component.
the Topics component has link to '/topics/:topicId' and i tried using switch but it didn't resolve.
App component is
class App extends Component{
render(){
return(
<BrowserRouter>
<div>
<Link to={'/'}>Home</Link>
<Link to={'/topics'}>Topics</Link>
<Route exact path={'/'} component={Home}/>
<Route path='/topics' component={Topics}/>
</div>
</BrowserRouter>
);
}
}
Topics Component
function Topics({match}){
console.log("topics");
return (
<div>
{topics.map(({name,id}) => (
<li key={id}>
<Link to={`${match.url}/${id}`}>{name}</Link>
<Route exact path={`${match.url}/:topicId`} component={Topic}/>
</li>
))}
</div>
);
}
Topic Component
function Topic({match}){
const topic=topics.find(t=>
t.id===match.params.topicId;
);
return (
<div>
{topic.name}
</div>
);
}
and the output when i click the link /topics is
/topics
output when i click /topics/react-js
/topics/react-js
as you can see react-js is displayed twice because /topics is again executed and then /topics/react-js.
Could Someone please help me out.
First import "Switch" from react-router-dom.Then use it as
class App extends Component{
render(){
return(
<BrowserRouter>
<div>
<Link to={'/'}>Home</Link>
<Link to={'/topics'}>Topics</Link>
<Switch>
<Route exact path={'/'} component={Home}/>
<Route path='/topics' component={Topics}/>
</Switch>
</div>
</BrowserRouter>
);
}
}
Im new to react and im having issues with the routing. I want the navbar to render on some pages but not others.What is the correct way to do this? I know im not supposed to render it in specific components.
so if this is my app.js
var App = React.createClass ({
render (){
return (
<div>
<NavbarInstance />
</div>
);
}
});
document.write('<div id="container"></div>');
ReactDom.render(
<Router history={createHistory({ queryKey: false })}
onUpdate={() => window.scrollTo(0, 0)}>
<Route path="/" component={App} />
<Route path="/login" component={LoginForm} />
<Route path="/other" component={Other} />
</Router>,
document.getElementById('container')
);
and this is my login page(see navbar instance-incorrect)
import React from 'react';
import Input from 'react-bootstrap/lib/Input';
import NavbarInstance from './components/header.jsx';
const LoginForm = React.createClass({
getInitialState: function() {
return {
username:'',
password:''
}
},
render () {
return (
<div>
<NavbarInstance />
<div className = "col-sm-12">
<h3> Log In </h3>
</div>
<div className ="col-sm-6">
<Input type = "text"
placeholder ="Username"
/>
<Input type= "password"
placeholder="Password"
/>
</div>
</div>
)
}
})
export default LoginForm
One option would be to keep track of what page you are in within a state variable within your main App component. Then add a check (say you didn't want to render it if page is 'index'.
return (
{ if (this.state.page !== 'index')
return <NavbarInstance />
}
)