I have an App component witch contains two child: A navbar and a container.
When I click on a li on the navbar I'm passing a react component trough the parent, but it doesen't wrok.
App:
function App() {
const [appState, setAppState] = useState();
useEffect(() => {
console.log(appState);
}, [appState])
return (
<div className="App">
<Nav stateSetter={setAppState}/>
<Container state={appState}/>
</div>
);
}
Navbar:
function Nav(props) {
return (
<div>
<div className="Nav" id="nav">
<nav>
<ul>
<li><button><span>App</span></button></li>
<li><button onClick={() => props.stateSetter("")}>Home</button></li>
<li><button onClick={() => props.stateSetter("")}>Products</button></li>
<li><button onClick={() => props.stateSetter("")}>About Us</button></li>
<li><button onClick={() => props.stateSetter(<Login />)}>Log in</button></li>
</ul>
</nav>
</div>
</div>
);
}
I only made the passing with the Login.
Container:
function Container(props) {
const [renders, setRenders] = useState(props.state);
console.log(renders);
return (
<div>
<div className="container">
{renders}
</div>
</div>
);
}
State is preserved for the "same" component across renders, which is its primary purpose. When you do a useState, you can pass the initial value for your state, but that state can henceforth only be changed with the setState function. So on first render, your Container has renders set to undefined (the initial property value passed by the parent). When this props.state prop is passed in later on, it's not going to change your state.
You should consider not using state in Container for this and allow the parent to control it; if Container needs the prop to change, you can use a callback instead:
function Container({ state: content }) {
return (
<div>
<div className="container">
{content}
</div>
</div>
);
}
react has a built in prop for passing components to Children props.children
you can pass a component to this prop as so
<Child><h1>passing text</h1></Child>
And you can access this from the Child like so
return (
<div>{props.children}</div>
)
Although the other answers address your problem, passing around components to navigate through your app would become messy and difficult to build on top of. Another approach that you should consider is using React Router which handles the rendering of components for you.
With this package, your code would look something like this:
App:
// Node Modules
import React from 'react';
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
// Page Components
import Home from './Home';
import About from './About';
import Products from './Products';
import Login from './Login';
function App() {
const [appState, setAppState] = useState();
useEffect(() => {
console.log(appState);
}, [appState])
return (
<div className="App">
<Nav stateSetter={setAppState}/>
<Router>
<Route to="/" component={Home} />
<Route to="/about" component={About} />
<Route to="/products" component={Products} />
<Route to="/login" component={Login} />
</Router>
</div>
);
}
Navbar:
// Node Modules
import {Link} from 'react-router-dom'
function Nav(props) {
return (
<div>
<div className="Nav" id="nav">
<nav>
<ul>
<li><button><span>App</span></button></li>
<li><Link to="/">Home</Link></li>
<li><Link to="/products">Products</Link></li>
<li><Link to="/about">About Us</Link></li>
<li><Link to="/login">Login</li>
</ul>
</nav>
</div>
</div>
);
}
This will remove the need for you container component and will allow you to organize your page components in a way that is easier to develop on. It will also remove the need to have an useState() in your App component to keep track of your page components.
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.
In a function, I have a button that displays a component on click. How do I hide this component when clicking on that button again (which would work like a toggle)?
<Link to="/">
<div className="navigation">
<button
className="about-button"
>
About
</button>
</div>
</Link>
<Switch>
<Route path="/" exact>
<HomePage />
</Route>
</Switch>
Your doing this a bit different then how you normally would approach this. Let me write a quick component from scratch to show you the idea...
import React, { useState } from 'react'
export default const ExampleComponent = () => {
const [showElem, setShowElem] = useState(true)
return (
<div>
{ showElem && <h1>Hello</h1> }
<Button onClick={() => {
setShowElem(!showElem)
}} />
</div>
)
}
...You'll have to excuse the formatting I typed this up right here.
I understand now that toggling is not recommended with React Routing.
I have a problem with my page that I build. There is main route path like "/" where is all page but there is also route path "/privacy" where you can go by clicking button "Privacy policy". Main navigation and footer with navigation are displaying at "/" and "/privacy" also.
It looks like this:
<Route exact path="/">
<Header />
<Main />
<Footer />
</Route>
<Route path="/privacy">
<Header />
<Privacy />
<Footer />
</Route>
The Main component looks like this
const Main = () => {
return (
<>
<Hello />
<Services />
<Projects />
<About />
<Contact />
</>
)}
All buttons in nav are react-scroll links.
<ul>
<li><Link to="header" smooth="true" duration={1000}>Main</Link></li>
<li><Link to="services" smooth="true" duration={1000}>Services</Link></li>
<li><Link to="webdev" smooth="true" duration={1000}>Portfolio</Link></li>
<li><Link to="about" smooth="true" duration={1000}>About</Link></li>
<li><Link to="contact" smooth="true" duration={1000}>Contact</Link></li>
</ul>
How can I redirect user from "/privacy" and scroll to - for example - about component at my "/" route path when he clicks "About" button in nav?
Example:
User is at "/privacy" and he wants to read "About" section, so he clicks button "About" in nav and then website is redirecting to "/" and scrolling to "About" section.
So. Add to component / root element of component about id="about" and then in your link set path <Link to="/#about"......
You can find info how to make links to content on the same page here (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
I used HashLink from the library react-router-hash-link. I simulated the home sections with two components Component1 and Component2 in order to make it more generic.
It's necessary install two packages
npm install react-router-dom
npm install react-router-hash-link
Here is the code:
Set the routes in the App.jsx
App.jsx
import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { Home } from "./components/Home";
import { Component0 } from "./components/Component0";
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/component0" element={<Component0 />} />
</Routes>
</Router>
);
}
export default App;
Home contains Component1 and Component2 and a button for navigating to Component0
Home.jsx
import React from 'react';
import { Component1 } from './Component1';
import { Component2 } from './Component2';
import { HashLink } from 'react-router-hash-link';
export const Home = props =>
{
return (<>
<HashLink to="/component0">
<button>Button component 0</button>
</HashLink>
<Component1/>
<Component2/>
</>);
}
The Component0 is a separated section from which we can navigate to Component1 or Component2 by scrolling within the Home component. To navigate we use the HashLink with a wrapped button
Component.jsx
import React from 'react';
import { HashLink } from 'react-router-hash-link';
export const Component0 = props =>
{
return (<>
<HashLink smooth to="/#section-component1">
<button>Component1</button>
</HashLink>
<HashLink smooth to="/#section-component2">
<button>Component2</button>
</HashLink>
</>);
}
Component1 and Component2
Component1.jsx
import React from 'react';
import "./Component1.css"
export const Component1 = props =>
{
return (<>
<section id="section-component1">
<h1>Section of component 1</h1>
</section>
</>);
}
Component2.jsx
import React from 'react';
import "./Component2.css"
export const Component2 = props =>
{
return (<>
<section id="section-component2">
<h1>Section of component 2</h1>
</section>
</>);
}
Repo: https://github.com/JCaeta/react-navigation
so i had a navbar component that has a <Link></Link> inside of it the problem in i couldn't use that link for the router (it wont refresh) when i clicked on it although the link appears on the URL but it didn't refresh
here's the code
import React, { Component } from 'react'
import {BrowserRouter as Router} from 'react-router-dom'
import Route from 'react-router-dom/Route'
import Nav from './Nav'
export class App extends Component {
render() {
return (
<div className="App">
<Router>
{/* NAVBAR */}
<Nav />
<Route path="/" exact render={
() => <h1>home</h1>
}/>
<Route path="/about" exact render={
() => <h1>about</h1>
}/>
<Route path="/author" exact render={
() => <h1>author</h1>
}/>
</Router>
</div>
)
}
}
export default App
and here's the navbar code
import React, { Component } from 'react'
import styles from './Nav.module.css'
import {BrowserRouter as Router} from 'react-router-dom'
import {Link} from 'react-router-dom'
export class Nav extends Component {
render() {
return (
<Router>
<div className={styles.nav}>
<div className="container">
<div className={styles.navgrid}>
<img className={styles.image} src="/img/actualLogo#1x.svg" alt="?"/>
<ul className={styles.ultest}>
<li><Link to="/">Home</Link></li>
<li><Link to="/updates">Updates</Link></li>
<li><Link to="/author">Author</Link></li>
</ul>
</div>
</div>
</div>
</Router>
)
}
}
export default Nav
I'm assuming it's because it's not on the same <Router></Router> but does anyone have a way to make this work?
You're creating a new <Router>, which has no defined <Route> elements within it. Remove that router:
export class Nav extends Component {
render() {
return (
<div className={styles.nav}>
<div className="container">
<div className={styles.navgrid}>
<img className={styles.image} src="/img/actualLogo#1x.svg" alt="?"/>
<ul className={styles.ultest}>
<li><Link to="/">Home</Link></li>
<li><Link to="/updates">Updates</Link></li>
<li><Link to="/author">Author</Link></li>
</ul>
</div>
</div>
</div>
)
}
}
Each component doesn't need its own <Router>, as long as they're all contained within (descendants of) the one defined in <App>.
I am new in Reactjs and I want to use router but not working,displaying blank page.
How can I use router Home category and products.I put code in App.jsx and index.jsx but showing me blank page,how can I resolve this.
Following is my App.jsx code
/* Import statements */
import React, { Component } from 'react';
import { Link, Route, Switch } from 'react-router-dom';
/* Home component */
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
/* Category component */
const Category = () => (
<div>
<h2>Category</h2>
</div>
)
/* Products component */
const Products = () => (
<div>
<h2>Products</h2>
</div>
)
/* App component */
class App extends React.Component {
render() {
return (
<div>
<nav className="navbar navbar-light">
<ul className="nav navbar-nav">
/* Link components are used for linking to other views */
<li><Link to="/">Homes</Link></li>
<li><Link to="/category">Category</Link></li>
<li><Link to="/products">Products</Link></li>
</ul>
</nav>
/* Route components are rendered if the path prop matches the current URL */
<Route path="/" component={Home}/>
<Route path="/category" component={Category}/>
<Route path="/products" component={Products}/>
</div>
)
}
}
Here is my index.jsx code
import React from 'react';
import { render } from 'react-dom';
import { App } from './components/App';
import './style.less';
render(<App />, document.getElementById('container'));
You need to import a BrowserRouter and wrap the whole app code into that component for routes can react to url changes, so in your import react-router-dom
import { BrowserRouter, Route, Link } from “react-router-dom”
return (
<BrowserRouter>
<div>
<nav className="navbar navbar-light">
<ul className="nav navbar-nav">
/* Link components are used for linking to other views */
<li><Link to="/">Homes</Link></li>
<li><Link to="/category">Category</Link></li>
<li><Link to="/products">Products</Link></li>
</ul>
</nav>
/* Route components are rendered if the path prop matches the current URL */
<Switch>
<Route path="/" component={Home}/>
<Route path="/category" component={Category}/>
<Route path="/products" component={Products}/>
</Switch>
</div>
</BrowserRouter>
)
Doing that you will get a working example, so BrowserRouter will listen for changes done into url and react that changes into its Route components, remember you should need pass to eachRoute component a property called exact={true} or even better wrap all your Route components with Switch component, that prevent to display all Route when a change url is done, with Switch will render only the route that matches with the exact path