I'm new to React(1 week :P). I have an app that hits an api based on a search term. From those results a user is able to favorite items from the results. When a I clicks on the link for favorites, I am directed to the correct component and the url reflects this change. However, when I enter a new search term, from the side navigation bar that is statically there always, I am presented with the correect information in the correct component, but the url does not change; it still says http://localhost:3000/favorites where it should be http://localhost:3000. Here is the relevant code, if there is any more that you feel is needed to hazard a guess please let me know.
The routes:
return(
<BrowserRouter >
<div className='routes'>
<Route path='/' component={App}/>
<Route path='/favorites' component={Favorites}/>
</div>
</BrowserRouter>
) }
The SearchBox component:
return(
<form className="search-box" >
<input type="text" placeholder="Search.." name="search" autoComplete='off'/>
<button className="fa fa-search" type="submit" onClick={this.handleSearch.bind(this)}>
</button>
</form>
)
And the SideNav component with the links:
return(
<nav className='naviagtion'>
<ul className='mainmenu'>
<div className='img-logout'>
<img src={this.props.info.image} alt='Avatar' />
<Logout handleLogout={this.handleLogout.bind(this)}/>
</div>
<SearchBox search={this.searchHandler.bind(this)}/>
<li>
home
</li>
<li>
favorites
</li>
<li>
playlists
<ul className='submenu'>
<li>
<a href="">
<strong>list of lists</strong>
</a>
</li>
</ul>
</li>
<li>
friends
</li>
</ul>
</nav>
)
I've seen a lot of information of the url changing but the component not rendering. That is not my problem. Then component is rendering correctly, however the url is not reflecting that.
EDIT:
Here is where the SideBar is being rendered in the Home Component.
<div>
<SideBar
info={this.state.info}
logout={this.handleLogout.bind(this)}
search={this.handleSearch.bind(this)}
/>
<Main videos={this.state.videos}/>
</div>
And here is the App.js
<div className='App'>
{localStorage.userData === undefined
? this.renderLogin()
: <Home logout={this.logout.bind(this)} deets=
{localStorage.userData}/>}
</div>
A couple things that might help.
1) The Route component goes inside the Switch component (make sure to import). Also, make sure to use "exact path" for "/" or the user won't make it to "/favorites".
return(
<Switch>
<div className='routes'>
<Route exact path='/' component={App}/>
<Route path='/favorites' component={Favorites}/>
</div>
</Switch>
) }
2) BrowserRouter goes around the whole app (probably in your index.js), which should look something like this:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom" OR "react-router"
import App from "./src/App";
ReactDOM.render(<BrowserRouter><App/></BrowserRouter>, document.getElementById("app"));
3) The Route components may need to be direct children of Switch, so I'd try removing the div in between. I'll look into it and update this answer when I figure it out.
4) You need to use the Link component instead of an a tag to actually link to the Route's you've set up:
import { Link } from "react-router-dom" OR "react-router" //not sure what you're using
...
return(
<nav className='naviagtion'>
<ul className='mainmenu'>
...
<li>
<Link to="/">home</Link>
</li>
<li>
<Link to="/favorites">favorites</Link>
</li>
...
</ul>
)
Related
So I'm trying to use the href at the bottom to link to Twitter? When putting an atag I get an error. is there another function I can use?
Ps. what I'm trying to do is on my home page have a picture that when the user clicks on it redirects them to Twitter.
I looked at other questions but it is not the same as mine. mine is trying to put a href inside a function.
Just added m carditem.JS components as well. Thank you !
import React from "react";
import "./Cards.css";
import CardItem from "./CardItem";
import { Link } from "react-router-dom";
function Cards() {
return (
<div className="cards">
<h1>Lost Fantom Saga Projects</h1>
<div className="cards__container">
<div className="cards__wrapper">
<ul className="cards__items">
<CardItem
src="images/img-9.jpg"
text="Lost Fantom Warrios"
label="Warriors"
path="/services"
/>
<CardItem
src="images/img-2.jpg"
text="Lost Fantom Disciples"
label="Disciples"
path="/services"
/>
</ul>
<ul className="cards__items">
<CardItem
src="images/img-3.jpg"
text="Fantom Degens"
label="Degens"
path="/services"
/>
<CardItem
src="images/img-4.jpg"
text="Coming Soon"
label="Coming Soon"
path="/products"
/>
<CardItem
src="images/img-4.jpg"
text="Coming Soon"
label="Coming Soon"
href="https://twitter.com/LostFantomSaga/"
target="_blank"
/>
</ul>
</div>
</div>
</div>
);
}
export default Cards;
import React from 'react';
import { Link } from 'react-router-dom';
function CardItem(props) {
return (
<>
<li className='cards__item'>
<Link className='cards__item__link' to={props.path}>
<figure className='cards__item__pic-wrap' data-category={props.label}>
<img
className='cards__item__img'
alt='Travel Image'
src={props.src}
/>
</figure>
<div className='cards__item__info'>
<h5 className='cards__item__text'>{props.text}</h5>
</div>
</Link>
</li>
</>
);
}
export default CardItem;
One simple approach that might suit your needs would be to use a <a> tag instead of the Link component.
Here's a quick and dirty CodeSandbox for how you could go about this, based on the code snippets you provided - https://codesandbox.io/s/lingering-sky-d4lz21?file=/src/CardItem.tsx. It demonstrates the ability to slightly alter the final render by using either props.path to use a Link component, or props.href to use a <a> tag (along with props.target for the target attribute).
Thank you for opening this page in advance.
I am a self-taught coder. And now I am making my personal page with Bootstrap.
What I want to do now is; SPA feature of React.js. All I understand this feature is;
install "react-router-dom",
import { Link, NavLink } from "react-router-dom";
And replace those anchor and href tag to Link to=
The following code is in 'src' folder.
Navbar.js
import React from "react";
import logoImage from "../components/logo.png";
// React fontawesome imports
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faBars } from "#fortawesome/free-solid-svg-icons";
import { Link, NavLink } from "react-router-dom";
const Navbar = () => {
return (
<nav className="navbar navbar-expand-lg navbar-light bg-white">
<div className="container-fluid">
<a className="navbar-brand mr-auto" href="#"><img className="logo" src={logoImage} alt="logoImage"/></a
<button
className="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<FontAwesomeIcon icon={faBars} style={{ color: "#2ff1f2" }}/>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<a className="nav-link active" aria-current="page" href="../components/About">About me</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Thoughts</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Portfolio</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Contacts</a>
</li>
</ul>
</div>
</div>
</nav>
)
}
export default Navbar;
App.js
import './App.css';
import "bootstrap/dist/css/bootstrap.min.css";
import Button from "react-bootstrap/Button";
import Particles from "react-particles-js";
import Navbar from "./components/Navbar";
import Header from "./components/Header";
import About from "./components/About";
function App() {
return (
<>
<Particles
className="particles-canvas"
params={{
particles: {
number: {
value: 30,
density: {
enable: true,
value_area: 900
}},
shape: {
type: "star",
stroke: {
width: 6,
color: "#f9ab00"
}}}}}
/>
<Navbar />
<Header />
<About />
</>
);
}
export default App;
Header.js
import React from "react";
import Typed from "react-typed";
import { Link } from "react-router-dom";
const Header = () => {
return (
<div className="header-wraper">
<div className="main-info">
<h1>Welcome, this is my own personal page</h1>
<Typed
className="typed-text"
strings={["text message to display in the centre of the page"]}
typeSpeed={80}
/>
Details
</div>
</div>
)
}
export default Header;
And soon as I replace
<a className="nav-link" href="#">Thoughts</a>
to
<Link to="../components/About">Thoughts</Link>
It stops working with this following error message.
×
Error: Invariant failed: You should not use <Link> outside a <Router>
invariant
C:/Users/Administrator/my-portfolio/node_modules/tiny-invariant/dist/tiny-invariant.esm.js:10
(anonymous function)
C:/Users/Administrator/modules/Link.js:88
85 | return (
86 | <RouterContext.Consumer>
87 | {context => {
> 88 | invariant(context, "You should not use <Link> outside a <Router>");
| ^ 89 |
90 | const { history } = context;
91 |
My understanding to this error is:
I should make Router.js file in src folder.
I should just start again without Bootstrap first. Once SPA feature is done, then I can start work on this CSS feature as CSS in JS (e.g. const something = div.styled ``;)
I know this sounds ridiculous, but this is the best option I could think for now.
Question is, Where should I begin investigating this error message?
I am currently relying on this document page to remove the error message.
1st Example: Basic Routing - https://reactrouter.com/web/guides/quick-start
I would appreciate your opinion. Thank you.
If I found a solution, I will update it with mine here.
This is a good question, but, in order to answer it the best way, you will need to work with several files, as I'm sure you're already aware of.
To start, assuming you used create-react-app, go to the index.js file, and wrap everything from the first parameter with react-router-dom's BrowserRouter component. It should look like the following:
index.js
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>,
document.getElementById("root")
);
Next, you will want to use react-router-dom's Switch component to wrap all the application's routes.
App.js
import { Route, Switch } from "react-router";
import Navbar from "./components/Navbar";
import Header from "./components/Header";
import About from "./components/About";
// Particles component removed for explanation
function App() {
return (
<Navbar />
<Header />
// When a link is clicked, the component will appear within the following div,
// so if you want certain elements to stay where they are on the page, wrap
// and place the Switch component accordingly.
<div className='pages'>
<Switch>
<Route path='/about' component={About} />
<Route path='/profile' component={profile} />
<Route path='/thoughts' component={Thoughts} />
<Route path='/contacts' component={Contacts} />
</Switch>
</div>
);
}
export default App;
Now, within any child component of App, you can use react-router-dom Links (I personally prefer using NavLink due to its ease of styling). This could be done by the following:
Navbar.js
import { NavLink } from "react-router-dom";
const Navbar = (props) => {
return (
<nav className="navbar navbar-expand-lg navbar-light bg-white">
<div className="container-fluid">
<NavLink className="navbar-brand mr-auto" to='/home'>
<img className="logo" src={logoImage} alt="logoImage"/>
</NavLink
<button
className="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<FontAwesomeIcon icon={faBars} style={{ color: "#2ff1f2" }}/>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<NavLink className="nav-link active" to='/about'>About me</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to='/thoughts'>Thoughts</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to='/portfolio'>Portfolio</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to='/contacts'>Contacts</NavLink>
</li>
</ul>
</div>
</div>
</nav>
)
};
export default Navbar;
After doing what is shown below, you will be able to navigate throughout your page using react-router-dom.
Router is a component provided by react-router-dom As the error says, Link can be used inside Router.
Also, path for Link should actual browser url and not the path of the component. Ideal way is to add routes for each component.
For Example your App can be like this: (Only for reference)
function App() {
return (
<Router>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/">
<Navbar />
</Route>
</Switch>
</Router>
);
}
Yes, you can do that, this error happen since you are missing to wrap <Link> component via <Router>...
If you like to put it for all project, you can simply do this:
<Router>
<App />
</Router>
Example:
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
In the context of the DOM how do I change the order of how the links for a react router setup?
See the following example:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import 'bootstrap/dist/css/bootstrap.css';
import Counter from './components/counter';
import Counters from './components/counters';
import ColorPicker from './components/colorpicker';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
ReactDOM.render(
<main className="content-area">
<Router>
<Route path="/counter" component={Counter} />
<Route path="/color-picker" component={ColorPicker} />
<ul>
<li>
<Link to="/">Main Page</Link>
</li>
<li>
<Link to="/counter">Counter</Link>
</li>
<li>
<Link to="/color-picker">Color Picker</Link>
</li>
</ul>
</Router>
</main>,
document.getElementById('root')
);
This is the output:
The links need to be above the outputted component, so:
But I don't know how to figure it out, and there are no helpful answers on stack overflow.
I tried:
ReactDOM.render(
document.getElementById('root'),
<main className="content-area">
<Router>
<Route path="/counter" component={Counter} />
<Route path="/color-picker" component={ColorPicker} />
<ul>
<li>
<Link to="/">Main Page</Link>
</li>
<li>
<Link to="/counter">Counter</Link>
</li>
<li>
<Link to="/color-picker">Color Picker</Link>
</li>
</ul>
</Router>
</main>
);
But everything goes blank with no errors.
I feel like this answer - Using React-Router with a layout page or multiple components per page - could be what I'm looking for but to be honest I don't understand it.
How do I change the order of react router links?
As #azium said in the comments, you need to reorder your html code to put the links before the routes, not reorder the arguments of the ReactDOM.render method.
ReactDOM.render(
<main className="content-area">
<Router>
<ul>
<li>
<Link to="/">Main Page</Link>
</li>
<li>
<Link to="/counter">Counter</Link>
</li>
<li>
<Link to="/color-picker">Color Picker</Link>
</li>
</ul>
<Route path="/counter" component={Counter} />
<Route path="/color-picker" component={ColorPicker} />
</Router>
</main>,
document.getElementById('root')
);
Im learning now the ReactJS and I read a lot of topics about this article, but I can't find a right solution for my problem.
I want to add a active class to li item not a, like
<li class="active">Item</li>
not
<li>Item</li>
This is my reactJS code
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link, Redirect, Switch } from "react-router-dom";
const Content = () => (
<Router>
<div className="content">
<div className="navigation">
<ul>
<li>
<Link to="/app">Wallets</Link>
</li>
<li>
<Link to="/backup">Backup</Link>
</li>
<li>
<Link to="/keys">Private keys</Link>
</li>
<li>
<Link to="/security">Security</Link>
</li>
<li>
How it works
</li>
</ul>
</div>
<div className="wrapper">
<Switch>
<Route path="/app" component={App} />
<Route path="/backup" component={Backup} />
<Route path="/keys" component={Keys} />
<Route path="/security" component={Security} />
<Redirect to="/app" />
</Switch>
</div>
</div>
</Router>
);
...
export default Content;
You can use NavLink, it has a property for the active Links:
import { NavLink } from 'react-router-dom';
After:
<ul>
<li>
<NavLink to="YOUR_ROUTE" exact activeClassName="link-active">
{ YOUR_CONTENT }
</NavLink>
</li>
</ul>
Now your links which are actives will have link-active class name.
activeClassName
The className a receives when its route is active. No active class by default.
https://knowbody.github.io/react-router-docs/api/Link.html
I'm trying to display a page within the Home page, so to speak, by clicking a link in a navigation bar that then displays a "square" of information without leaving the Home page. This is my Home:
import React, { Component } from 'react';
import { Link } from 'react-router';
export default class Home extends Component {
var Music = React.createClass({
render: function() {
return (
<div>
<h2> BBB </h2>
</div>
);
}
});
render() {
return (
<div className='Home' id='Home'>
<div id='musicMenu'>
<ul>
<li id="music"><Link to="/music">Music</Link></li>
<li id="shows"><Link to="/shows">Shows</Link></li>
<li id="collections"><Link to="/collections">Collections</Link></li>
</ul>
</div>
</div>
);
}
}
This is my app.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute, hashHistory } from 'react-router';
import App from 'views/App';
import Home from 'views/Home';
import About from 'views/About';
import Cart from 'views/webcart';
import Music from 'views/music';
import Shows from 'views/shows';
import Collections from 'views/collections';
ReactDOM.render(
<Router history={ hashHistory }>
<Route path='/' component={ App }>
<IndexRoute component={ Home } />
<Route path='about' component={ About } />
<Route path='Cart' component={ Cart } />
<Route path='music' component={ Music } />
<Route path='shows' component={ Shows } />
<Route path='collections' component={ Collections } />
</Route>
</Router>,
document.getElementById('app') // eslint-disable-line
);
The error I'm getting in Webpack is
ERROR in ./js/views/Home.js
Module build failed: SyntaxError: Unexpected token, expected
and points to var Music. How can I fix this error? Also, is this the best way to do this or can anyone recommend a better way?
You can't have a var within the Home class. That's not allowed in JS. Move it outside just below the imports.
Also the square you want to display is this component?
<div>
<h2> BBB </h2>
</div>
Add a CSS class called .invisible like this
.invisible{
display:none;
}
And then in the home state do something like
this.state = {
showSquare:false
}
And in the render
<div className='Home' id='Home'>
<div className={this.state.showSquare?'':'invisible'}>
<h2> BBB </h2>
</div>
<div id='musicMenu'>
<ul>
<li id="music"><Link to="/music">Music</Link></li>
<li id="shows"><Link to="/shows">Shows</Link></li>
<li id="collections"><Link to="/collections">Collections</Link></li>
</ul>
</div>
</div>
What this does is make the square invisible when this.state.showSquare is false. Then in the navigation bar add a click handler which changes the state.showSquare
<li onClick={this.toggleShowSquare}>Show Square</li>
where toggleShowSquare() is
toggleShowSquare(){
this.setState((prevState)=>({showSquare:!prevState.showSquare}))
}
Remember to do a
this.toggleShowSquare = this.toggleShowSquare.bind(this) in the constructor
EDIT: Replying to comment.
For multiple divs do this
this.state = {
showSquareOne:false,
showSquareTwo:false
}
Then have the divs like this
<div className={this.state.showSquareOne?'':'invisible'}></div>
<div className={this.state.showSquareTwo?'':'invisible'}></div>
The li elements like this
<li onClick={()=>this.toggleShowSquare('showSquareOne')}>Show Square One</li>
<li onClick={()=>this.toggleShowSquare('showSquareTwo')}>Show Square Two</li>
And the function like this
toggleShowSquare(property){
this.setState((prevState)=>({[property]:!prevState[property]}))
}