Passing State of App.js to Child Component - javascript

I'm working on the main page of a website and I'd like to have a specific nav/menu bar for the main page and a different one for the other components (the main page hides de "home" button and the others show it).
The issue I have at the moment is that the logic of rendering this menu lives on App and I'm having a hard time to find the proper way to pass the state of my App component to the other components, probably just because of the lack of experience.
import React from "react";
import { BrowserRouter, Route, Link } from "react-router-dom";
import Main from "./main";
import MapContainer from "./mapcontainer";
import Venue from "./venue";
import Schedule from "./schedule";
import Accommodation from "./accommodation";
import Couple from "./couple";
import Honeymoon from "./honeymoon";
import Uploader from "./uploader";
import Friday from "./friday";
import Saturday from "./saturday"
import Sunday from "./sunday";
import Dresscode from "./dresscode";
export class App extends React.Component {
constructor(props) {
super(props);
this.state = {
error: false,
isHome: true
};
}
componentDidMount() {
console.log("App mounted");
}
render() {
function HomeComponentMenu(props) {
return (
<nav className="header-on-app">
<button>Contact Us</button>
<button className="logout-btn">Logout</button>
</nav>
);
}
function AllOtherComponentsMenu(props) {
return (
<nav className="header-on-app">
<button><Link to="/">Home</Link></button>
<button>Contact Us</button>
<button className="logout-btn">Logout</button>
</nav>
);
}
const isHome = this.state.isHome;
let menu;
if (isHome) {
menu = <HomeComponentMenu/>;
} else {
menu = <AllOtherComponentsMenu/>;
}
return (
<BrowserRouter>
<nav className="header-on-app">{menu}</nav>
<div className="app-container">
<Route exact path="/" component={Main} />
<Route exact path="/venue" component={Venue}/>
<Route exact path="/venuemap" component={MapContainer}/>
<Route exact path="/schedule" component={Schedule}/>
<Route exact path="/accommodation" component={Accommodation}/>
<Route exact path="/couple" component={Couple}/>
<Route exact path="/honeymoon" component={Honeymoon}/>
<Route exact path="/uploader" component={Uploader} />
<Route exact path="/friday" component={Friday} />
<Route exact path="/saturday" component={Saturday} />
<Route exact path="/sunday" component={Sunday} />
<Route exact path="/dresscode" component={Dresscode} />
</div>
</BrowserRouter>
);
}
}
Component I'd like to set isHome to false
import MapContainer from "./mapcontainer";
export default class Venue extends React.Component {
constructor(props){
super(props);
this.state = {
error:false,
}
}
render() {
return (
<div className="venue-container">
<h1>Anna & Rodolfo</h1>
<h2><span>_______</span> Venue . Local . Veranstalungsort <span>_______</span></h2>
{this.state.error && <h2 className="error">Ops! Something went wrong.</h2>}
<div className="grid-container-venue">
<div className="item">
<img src="venue.png" alt="Avatar" className="image"/>
<div className="background-grid-items">
<div className="text-address">
<a href="https://www.g71972,15z/data=!4887b!8m2!3d52.47094!4d12.71972">
<p>Kulturschloss</p>
<p>Abcd.30 3456 Berlin </p>
<p>Germany . Alemanha . Deutschland</p>
</a>
</div>
</div>
</div>
<div className="item">
<img src="website.png" alt="Avatar" className="image"/>
<div className="background-grid-items">
<div className="text">
<a href="https://www.kult.de/">
<p>To the Website</p>
<p>Para o Website</p>
<p>Zur Website</p>
</a>
</div>
</div>
</div>
<div className="item">
<img src="transportation.png" alt="Avatar" className="image"/>
<div className="background-grid-items">
<div className="text">
<p>Transportation</p>
<p>Traslado</p>
<p>Transport</p>
</div>
</div>
</div>
<div className="item">
<div className="background-grid-venue">
<div className="map">
<MapContainer/>
</div>
</div>
</div>
</div>
</div>
);
}
}
Since my components are being rendered by React Router, I tried to render props passing it in an inline function and afterwards pass along to the argument I was creating, but somehow it didn't work. Would you have any suggestions on how to solve this? Thank you very much!

To pass a state to a child component, you have to pass it as props of the child component.
e.g.
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import TableView from './TableView'
export default class App extends Component {
state = {
item: 'this is the item'
}
render() {
return(
<Router>
<Route exact path="/home">
<TableView itemList={this.state.item}></TableView>
</Route>
</Router>
)
}
}
to get the props in the child component
import React, { Component } from 'react'
export default class TableView extends Component {
render(){
<React.Fragment>
{this.props.item}
</React.Fragment>
}
}
Hope it helps
EDIT:
It would also help to debug if you have the react devtools addons in your browser to check if the values of the state of each component

To pass props to a react route you have to define it in the render function like this:
<Route exact path="/venue" render={(props) => <Venue updateHomeState={this.updateHomeState}/>}/>
To alter the isHome state on the parent, you could define that function on the parent like:
updateHomeState = (newState) => {
this.setState({ isHome: newState })
}
And then call it in componentDidMount() of your child component like this.props.updateHomeState(newState).

Related

React Router - Why is the switch not changing html when the path changes?

I am working on a web app, and i am having some issues with reactJS Router. When i redirect to the /sell path the HTML form the / path stays, and the HTML inside the /sell route doesn't load.
Am i doing something wrong? would anyone be able to point me towards the right direction?
import React, { Component } from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Helmet from "react-helmet";
import CreateList from "./CreateList";
//https://colorhunt.co/palette/33990
//https://colorhunt.co/palette/66990
class Home extends Component {
constructor(props) {
super(props);
this.state = { appTitle: "better craigslist"};
}
render() {
return (
<React.Fragment>
<Helmet>
<title>{this.state.appTitle}</title>
</Helmet>
<Router>
<Switch>
<Route path="/">
<div id="header-text">
<h1 className="center-align">
<b>Sellify</b>
</h1>
<h5 className="center-align">
Need to get rid of your stuff? create a listing and sell it here! <br /> Looking for something? Check if its on selify!
</h5>
</div>
<div className="col s12 center">
<Router>
<Link to="/sell">
<button className="btn" id="create-listing-button">
Create Listing
</button>
</Link>
</Router>
</div>
</Route>
<Route path="/sell">
<h1>Test</h1>
</Route>
</Switch>
</Router>
</React.Fragment>
);
}
}
export default Home;
Thank you very much!
Issue
You've more than one Router. The inner Router context is handling the links so the outer Router isn't notified.
Solution
Use only one Router component, remove the Router around the Link. Additionally, when using a Switch, path order and specificity matter. You want to oder your more specific paths before less specific paths. "/" is a path prefix for all paths and would be matched and rendered before "/sell".
class Home extends Component {
constructor(props) {
super(props);
this.state = { appTitle: "better craigslist" };
}
render() {
return (
<React.Fragment>
<Helmet>
<title>{this.state.appTitle}</title>
</Helmet>
<Router>
<Switch>
<Route path="/sell">
<h1>Test</h1>
</Route>
<Route path="/">
...
<div className="col s12 center">
<Link to="/sell">
<button className="btn" id="create-listing-button">
Create Listing
</button>
</Link>
</div>
</Route>
</Switch>
</Router>
</React.Fragment>
);
}
}

React-router-dom rendering component on the same page

i am using react-router-dom in my project when i am proving routes instead of rendering the component in another page dom rendering component in the same page below my first component
My App.js
import React,{Component} from 'react';
import './App.css'
import Layout from './components/front/layout'
import FirstPage from './components/index/firstpage';
import {BrowserRouter ,Switch,Route} from 'react-router-dom';
class App extends Component {
render(){
return (
<div className="container">
<BrowserRouter>
<FirstPage/>
<Switch>
<Route path='/Layout' exact component={Layout} />
</Switch>
</BrowserRouter>
</div>
);
}
}
export default App;
My another middlePortion.js where i am using imported from react-router-dom to route to another page
import React from 'react';
import { Button, Form } from 'reactstrap';
import axios from 'axios';
import '../../css/style.css'
import {Link} from 'react-router-dom'
class Middleportion extends React.Component {
constructor(props){
super(props);
this.Submit = this.Submit.bind(this);
}
render() {
const layStyle={
color:'white'
};
return (
<div className='row frnt'>
<div className="col-md-3">
</div>
<div className="col-md-6 am ">
<div className="row align-items-center">
<div className="row justify-content-center bg-primary pp">
<ul className="list-unstyled">
<li><Link style={layStyle} to='/Layout'>
male
</Link></li>
</ul>
</div>
</div>
</div>
<div className="col-md-3">
</div>
</div>
);
}
}
export default Middleportion;
I want to render my Layout component on separate page but its rendering on the same page please help me out
The problem with your code is that you're rendering FirstPage manually as if to be hard coded.
In order to get FirstPage and Layout to render in separate routes, you need to create a separate route inside your <Switch> and use FirstPage as the component prop like you did with Layout.
It would look like this:
(
<div className="container">
<BrowserRouter>
<Switch>
<Route exact path='/' component={FirstPage} />
<Route exact path='/Layout' component={Layout} />
</Switch>
</BrowserRouter>
</div>
)
With the setup above, the FirstPage component would render only on the / route and the Layout component would only render on the /layout route.

React-Router Link Button not with Router?

I have a very simple react app.
In the main App.js I have a Routerwith my routes.
In another separate component, PostItem, which lives in MainComponent, I have a Link button to another component, JobPost.
I keep getting:
Cannot GET /job/7
Does this set up work? Or do I need to have a Router element in my component with my Link?
App.js:
import React from 'react';
import { render } from 'react-dom';
import MainComponent from './index.js';
import JobPost from './components/JobPost.js';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const App = () => (
<Router>
<div>
<Route path="/" exact component={MainComponent} />
<Route path="/job/:id" exact component={JobPost} />
</div>
</Router>
);
render(<App />, document.getElementById('root'));
PostItem.js:
import React from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
export default function PostItem(props){
return(
<div className="post-item">
<div className="job-details">
<h2 className="job-title" dangerouslySetInnerHTML={{__html: props.title }} />
<h3 className="job-location"> Test Company - <i>Test Location</i></h3>
<div className="job-description">
<span dangerouslySetInnerHTML={{__html: props.content }} />
</div>
</div>
<button className="view-btn">
<Link to={ `/job/` + props.id } >
View
</Link>
</button>
</div>
);
}
JobPost.js:
import React, { Component } from 'react';
//make actual class and render again
export default class JobPost extends Component{
constructor(props){
super(props);
this.state={
id: this.props.match.params.id
};
}
componentDidMount(){
//fetch id from component
console.log(this.state.id);
}
render(){
return(
<div className="post-container">
<div className="job-details">
<h2 className="job-title" dangerouslySetInnerHTML={{__html: props.title }} />
<h3 className="job-location"> Test Company - <i>Test Location</i></h3>
<div className="job-description">
<span dangerouslySetInnerHTML={{__html: props.content }} />
</div>
</div>
<button className="apply-btn">Apply</button>
</div>
);
}
}

How to render a component in a different page when click on a link in a table row in ReactJs

I'm a beginner in ReactJs, and I have a ProjectsList component which includes an html table. One of its columns is a link which when clicked it must navigate to a different page rendering a ProjectInfo component.
But, what happens is that the component is rendered in the same page of ProjectsList component at the end of the table.
ProjectsList component is rendered when clicked on a link Show Projects in Projects component.
Projects.component.jsx
import React, { Component } from "react";
import { Link, Route, Switch } from "react-router-dom";
import NewProject from "../NewProject/NewProject.component";
import ProjectsList from "../ProjectsList/ProjectsList.component";
import "./Projects.css";
export default class Projects extends Component {
render() {
return (
<div className="projects-dashboard">
<nav className="nav-up">
<ul>
<li>
<Link to={"/dashboard/projects/add"}>add project</Link>
</li>
<li>
<Link to={"/dashboard/projects/list"}>show projects</Link>
</li>
</ul>
</nav>
<main>
<Route path={"/dashboard/projects/add"} component={NewProject} />
<Route path={"/dashboard/projects/list"} component={ProjectsList} />
</main>
</div>
);
}
}
ProjectsList.component.jsx
import React, { Component } from "react";
import axios from "axios";
import { Route, Link } from "react-router-dom";
import "./ProjectsList.css";
import ProjectInfo from "../ProjectInfo/ProjectInfo.component";
export default class ProjectsList extends Component {
constructor(props) {
super(props);
this.state = {
allProject: []
}
}
componentWillMount() {
this.fetchAllProjects();
}
componentDidMount() {
document.body.style.overflowY = "auto";
}
fetchAllProjects = () => {
axios.get("/api/projects").then(res => {
this.setState({ allProject: res.data }, () => { console.log(this.state.allProject); });
});
};
render() {
const projects = this.state.allProject.map(project => {
return (
<tr>
<td>{project.id}</td>
<td>{project.title}</td>
<td>{project.organization_name}</td>
<td className="project-options">
<Link to={`/dashboard/projects/list/${project.id}`}>
<i className="far fa-eye" /> show
</Link>
</td>
</tr>
);
});
return (
<div>
<table class="projects-list-table">
<thead>
<tr>
<th>
<h1>Project ID</h1>
</th>
<th>
<h1>Project Name</h1>
</th>
<th>
<h1>Organization Name</h1>
</th>
<th>
<h1>Options</h1>
</th>
</tr>
</thead>
<tbody>{projects}</tbody>
</table>
<main>
<Route path={"/dashboard/projects/list/:id"} component={ProjectInfo} />
</main>
</div>
);
}
}
ProjectInfo.component.jsx
import React, { Component } from 'react';
import "./ProjectInfo.css";
export default class ProjectInfo extends Component {
render() {
return (
<div>
<h1>Project Info Component</h1>
</div>
)
}
}
React router includes those components to the specified section where the Route tag is. For instance:
<section>
<h1>Hello</h1>
<Route path={"/random/path"} component={MyComponent} />
</section>
will return
<section>
<h1>Hello</h1>
<MyComponent />
</section>
to get around this you need to add it to the same level of routing as your PrjectList route.
so change this
<main>
<Route path={"/dashboard/projects/add"} component={NewProject} />
<Route path={"/dashboard/projects/list"} component={ProjectsList} />
</main>
to
<main>
<Route path={"/dashboard/projects/add"} component={NewProject} />
<Route exact path={"/dashboard/projects/list"} component={ProjectsList} />
<Route exact path={"/dashboard/projects/list/:id"} component={ProjectInfo} />
</main>
EDIT
The last route should not have the exact tag on
<main>
<Route path={"/dashboard/projects/add"} component={NewProject} />
<Route exact path={"/dashboard/projects/list"} component={ProjectsList} />
<Route path={"/dashboard/projects/list/:id"} component={ProjectInfo} />
</main>
If you want to exclusively render a component, meaning that you want to only render one specific component (which in you case is ProjectInfo) when you click on the link in the table, and in this case you don't want to render the Projects component, you need to use Switch within the router.
From the official docs
<Switch>
Renders the first child <Route> or <Redirect> that
matches the location.
How is this different than just using a bunch of <Route>s?
<Switch> is unique in that it renders a route exclusively. In
contrast, every <Route> that matches the location renders
inclusively.
Consider this code:
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
If the URL is /about, then <About>, <User>, and <NoMatch> will all
render because they all match the path. This is by design, allowing us
to compose <Route>s into our apps in many ways, like sidebars and
breadcrumbs, bootstrap tabs, etc.
So, change your Projects component to something like this (You are already importing Switch so no need to import it again):
<main>
<Switch>
<Route exact path={"/dashboard/projects/add"} component={NewProject} />
<Route exact path={"/dashboard/projects/list"} component={ProjectsList} />
</Switch>
</main>

React Router- Link not directing properly

I have the following component...
import React from 'react';
import { Router, Route, Link, browserHistory, IndexRoute } from 'react-router'
class Bottom extends React.Component {
constructor(){
super();
this.state = {link:"Don't have an account?"}
}
render(){
return (
<div>
<div className="sub-login">
<p>{this.state.link}<Link to="/register"> Register here</Link></p>
</div>
</div>
);
}
}
export default Bottom;
As you can see I have a <Link> pointing to the page I want the user to go to if it is clicked.
This component is then bundled into another class called <Register />.
And then I have the following Routes...
class App extends React.Component {
render(){
return (
<Router history={hashHistory}>
<Route path='/' component={Index} >
<IndexRoute component={Register} />
<Route path='/register' component={Register} />
</Route>
</Router>
);
}
}
When the Link is clicked, the url changes to /register, but the content of the page is still that of the home page, which is <Index /> component.
Why won't it show the <Register /> component? What must I change to render the register component when the link is clicked?
I realized that all I had to do was add {this.props.children} to my Index Layout. So when the Link is clicked, the Register Layout will be loaded into my Index Layout.
The following code made it work...
render(){
return (
<div>
{this.props.children} <-----
<div className="sub-login">
<p>{this.state.link}<Link to="/register"> Register here</Link></p>
</div>
</div>
);

Categories

Resources