React won't render my components using router - html

I am very new to react and trying to work on my first website.
I have tried to seek my problem online, I've encountered similar questions to mine but could not figure out my exact problem.
My layout of components are in a scroll down style (portfolio), when I try route for example to my contact component it wont render unless I refresh my page. also instead of scrolling down to component it will pop up at the top .(Hope I am clear)
My App Function
import { useState } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';
import Contact from './Components/Contact/Contact';
import Form from './Components/FormArea/Form/form';
import Introdoction from './Components/Introdoction/Introdoction';
import NavBar from './Components/NavBar/NavBar';
import NavigationBar from './Components/NavigationBarHeader/NavigationBar/NavigationBar';
import Portfolio from './Components/Portfolio/Portfolio';
import Routing from './Components/Routing/Routing';
import Skills from './Components/Skills/Skills';
function App() {
return (
<BrowserRouter>
<Switch>
<div className="App">
<NavigationBar/>
<section className="section">
<Route path="/contact" component={Contact} exact/>
<Introdoction/>
<Portfolio/>
<Skills/>
{/* <Contact/> */}
<Form/>
</section>
</div>
</Switch>
</BrowserRouter>
);
}
export default App;
I am trying to configure "Contact" component for this example.
My Menu/Navbar Component
import { Component, MouseEventHandler } from "react";
import {MenuItems} from "../MenuItems/MenuItems";
import "./NavigationBar.css";
import icon from '../../../Assets/icon.png'
import {Button} from "../Button/Button";
import { NavLink, Redirect, Route, Switch, useHistory } from "react-router-dom";
import Contact from "../../Contact/Contact";
class NavigationBar extends Component {
state = {clicked : false}
handleClick = () => {
this.setState ( { clicked: !this.state.clicked } );
};
public render(): JSX.Element {
return (
<nav className="NavbarItems ">
<img className="navbar-logo"src={icon } />
<div className="menu-icon" onClick={this.handleClick}>
<i className={this.state.clicked ? 'fas fa-times' : 'fas times'}></i>
</div>
<ul className={this.state.clicked ? 'nav-menu active' : 'nav-menu'}>
{MenuItems.map((item,index) => {
return (
<li key={index}>
<NavLink to={item.url} className={item.cName} >{item.title} </NavLink>
</li>
)
})}
</ul>
<Button>Sign up</Button>
</nav>
);
}
}
export default NavigationBar;
ItemMenu Component
import { NavLink } from "react-router-dom";
import "./MenuItems.css";
export const MenuItems = [
{
title: 'Home',
url: '/Home',
cName: 'nav-links'
},
{
title: 'Introduction',
url: '/introduction',
cName: 'nav-links'
},
{
title: 'Skills',
url: '/skills',
cName: 'nav-links'
},
{
title: 'Projects',
url: '/projects',
cName: 'nav-links'
},
{
title: 'Contact',
url: '/contact',
cName: 'nav-links'
},
];
I could add more information if needed. I hope my question is clear on what my problem is.
Thanks.

If I understood your question correctly, you want one single page, with everything below each other, and when you press a link, it scrolls you down to that place. In that case I would use:
<Contact id="contact" />
react-router creates new sub pages, which you don't want (if I understood you correctly)

Related

Wrapping h5 in Link tag made h5 dissappear

I am trying to make a component go to localhost:3000/second. The header for the component(AddNote) displays when I dont wrap it in a Link tag, but when I do, the whole page becomes blank, including the "My Notes" which is supposed to be displayed by default.
import React, {useState} from 'react';
import './App.css';
import {BrowserRouter as Router, Routes, Route, Switch} from 'react-router-dom';
import AddNote from './components/noteDisplay/addNote/newNote.js'
import FirstPage from './components/noteDisplay/firstPage.js'
import NoteDisplay from './components/noteDisplay/noteDisplay.js'
import secondPage from './components/secondPage/secondContainer.js'
const App = () => {
return (
<div className="App">
<h1 className="app-title">My notes</h1>
<Router>
<div>
<Routes>
<Route path='/second' element={<secondPage />}/>
{/*<Route path='/' element={<NoteDisplay/>}/>*/}
</Routes>
</div>
</Router>
<AddNote/>
</div>
);
}
import React from 'react';
import { Route, BrowserRouter as Router, Link, Switch } from 'react-router-dom';
import NoteDisplay from '../noteDisplay';
import { v4 as uuidv4 } from 'uuid';
const AddNote = () => {
console.log('hi')
return (
<div>
<Link to="/second">
<h5 className="add-note">New note</h5>
</Link>
</div>
)
}
export default AddNote;
You need to change your <Link /> code to be something like below.
const AddNote = () => {
return (
<div>
<h5>
<Link href="/second">New Note</Link>
</h5>
</div>
);
};
See the official Next.js documentation for how to use it - it explains it in greater detail!

How to redirect page using Route?

I kinda wanna do a function that when i click on every item in the navbar and even the submenu in each item, it will rediret me to a new page with relevant information, i thought of using Route inside my Link tag but i kinda stuck in how to do that. Should i use Route or other codes to achive this task? I'd like to hear recommendations from you guys, thank you btw!
Navbar.js:
import React, { useState } from "react";
import { navItems } from "./NavItems";
import { Link, BrowserRouter as Router } from "react-router-dom";
import "./Navbar.css";
import DropDown from "./DropDown";
function Navbar() {
const [dropDown, setDropdown] = useState(false);
return (
<div>
<ul className="nav-items">
{navItems.map((item) => {
if (item.title === "Services") {
return (
<li
onClick={() => setDropdown(!dropDown)}
key={item.id}
className={item.cName}
onMouseEnter={() => setDropdown(true)}
onMouseLeave={() => setDropdown(false)}
>
<Router>
<Link to={item.path}>{item.title}</Link>
</Router>
{dropDown && <DropDown />}
</li>
);
}
return (
<Router>
<li key={item.id} className={item.cName}>
<Link to={item.path}>{item.title}</Link>
</li>
</Router>
);
})}
</ul>
</div>
);
}
export default Navbar;
DropDown.js:
import React from "react";
import { serviceDropdown } from "./NavItems";
import { Link, BrowserRouter as Router } from "react-router-dom";
import "./DropDown.css";
function DropDown() {
return (
<div>
<ul className="subnav-items">
{serviceDropdown.map((item) => {
return (
<Router>
<li key={item.id} className={item.cName}>
<Link to={item.path}>{item.title}</Link>
</li>
</Router>
);
})}
</ul>
</div>
);
}
export default DropDown;
Sandbox link: https://codesandbox.io/s/dropdown-menu-ho4h8?file=/src/components/DropDown.js:0-560
One possible solution would be to use the useHistory hook from react-router and use the push method to move to a different page. The code would look as follows
const history = useHistory();
// Use the onClick props of your dropdown element
onClick={() => history.push("other URL");}

Gatsby conditional className based on frontmatter

I'm trying to add a className of split to my header, based on the page template as defined in the frontmatter of a page. I've got a page template called split and want the header to have that class on pages that are utilizing the template. Here are my templates:
layout.js
import React from 'react'
import PropTypes from 'prop-types'
import Helmet from 'react-helmet'
import { StaticQuery, graphql } from 'gatsby'
import Header from './header'
import Footer from './footer'
import '../css/main.scss'
import favicon from './favicon.png'
const Layout = ({ children, frontmatter }) => (
<StaticQuery
query={graphql`
query PageInfoQuery {
site {
siteMetadata {
title
footer
}
}
markdownRemark {
frontmatter {
template
}
}
}
`}
render={data => (
<>
<Helmet
title={data.site.siteMetadata.title}
meta={[
{ name: 'description', content: 'Sample' },
{ name: 'keywords', content: 'sample, something' },
]}
link={[
{
rel: 'shortcut icon',
type: 'image/png',
href: `${favicon}`,
},
]}
>
<html lang="en" />
</Helmet>
<Header siteTitle={data.site.siteMetadata.title} frontmatter={data.markdownRemark.frontmatter}/>
{children}
<Footer footer={data.site.siteMetadata.footer} />
</>
)}
/>
)
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
header.js
import PropTypes from 'prop-types'
import React from 'react'
import Navbar from './navbar'
const Header = ({ siteTitle, frontmatter }) => (
<header className={ frontmatter.template === 'split' ? 'header split' : 'header' }>
<section className="navigation">
<Navbar siteTitle={siteTitle} />
</section>
</header>
)
Header.propTypes = {
siteTitle: PropTypes.string,
}
Header.defaultProps = {
siteTitle: '',
}
export default Header
I know that I've got the data.markdownRemark.frontmatter working correctly, as in my template split.js I'm able to display the template name dynamically in the hero element, using {post.frontmatter.template}. In the interest of being thorough I'll include that as well.
split.js
import React from 'react'
import Helmet from 'react-helmet'
// eslint-disable-next-line
import { Link, graphql } from 'gatsby'
import Layout from '../components/layout'
// import blocks
import Feature from '../components/blocks/feature'
import Hero from '../components/blocks/hero'
class BlocksTemplate extends React.Component {
render() {
const post = this.props.data.markdownRemark
const siteTitle = this.props.data.site.siteMetadata.title
const siteDescription = post.excerpt
const heroImage = post.frontmatter.hero_image.childImageSharp.fixed.src
return (
<Layout location={this.props.location} title={siteTitle}>
<Helmet
htmlAttribute={{ lang: 'en' }}
meta={[{ name: 'description', content: siteDescription }]}
title={`${post.frontmatter.title} • ${siteTitle}`}
/>
<section className="hero" style={{ backgroundImage: `url(${heroImage})` }}>
<h4 className="name">
<Link to="/">
{this.props.siteTitle}
{post.frontmatter.template}
</Link>
</h4>
</section>
{post.frontmatter.blocks.map(block => {
switch (block.component) {
case 'feature':
return <Feature block={block} />
case 'hero':
return <Hero block={block} />
default:
return ''
}
})}
</Layout>
)
}
}
export default BlocksTemplate
export const pageQuery = graphql`
query SplitPageBySlug($slug: String!) {
site {
siteMetadata {
title
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt
html
frontmatter {
template
title
hero_image {
childImageSharp {
fixed(width: 1500) {
src
}
}
}
blocks {
component
image {
childImageSharp {
fixed(width: 1500) {
src
}
}
}
}
}
}
}
`
Here is the header markup that is being rendered; in essence the split class is never being added.
<header class="header">
<section class="navigation">
<nav class="nav" role="navigation">
<div class="branding">
<h6 class="name">Jesse Winton</h6>
</div>
Home
<a aria-current="page" class="" href="/about-the-demo">What is this?</a>
About Gatsby
Blog
</nav>
</section>
</header>
I'm fairly new to Gatsby, so any help would be very much appreciated! Thank you!
In layout.js, you are passing frontmatter={data.markdownRemark.frontmatter} to the header from the query above it in layout.js. This is a staticQuery which will always return the same data.
I see you are querying for the correct data in the pageQuery in split.js, but this data is not passed along to the layout in split.js:
<Layout location={this.props.location} title={siteTitle}>
One way to fix this is to pass the template name to the layout props, just like you are already doing with location and title attributes.
Another way would be using the gatsby-plugin-layout plugin which return the old behavior from V1 Gatsby for the Layout component, adding a layout wrapper to every component. Then you could the pageContext to the split component directly.

How to pass my item from JSON to another page or class/component in ReactJS

I want to pass my data from one page to another but in an specific way.
I have a json brought via AJAX with this method (resp, error and result):
myArrayItems
import React, { Component } from 'react';
import logo from '../images/logo.png';
import '../App.css';
import { Container, Row, Col } from 'react-bootstrap';
import { Route, IndexRoute } from 'react-router';
import { BrowserRouter as Router, Switch, Link } from 'react-router-dom';
class myArrayItems extends Component {
componentDidMount() {
fetch("https://myrestserver/myArrayItems")
.then(response => response.json())
.then(
(result) => {
console.log(result)
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
And in my View i rendered like that with key.
<ul>
{items.map(item => (
<li key={item.title} className="list-group-item border-0">
<div className="wrapper">
<div className="myclass">
<Link to={{ pathname: "/myitem/" }} className="App-link">
<p className="text-left">{item.title}</p>
</Link>
</div>
</div>
</li>
))}
</ul>
}
export default myArrayItems;
So I want to pass the item.id, item.title, item.x to the page myitem, but i imported the myArrayItems and still get undefined.
What I want to achieve is in my first class to display a list of items (What i did) but when i click on any of these items, to access them in the page myitem.
myitem.js
import React, { Component } from 'react';
import logo from '../images/logo.png';
import '../App.css';
import { Container, Row, Col } from 'react-bootstrap';
import { Route, IndexRoute } from 'react-router';
import myArrayItems from './myArrayItems';
const Background = {
background: '#004272'
}
class myitem extends Component {
render(){
return (
<div className="App">
<header style={Background} className="text-center py-2 m-0">
<img src={logo} className="img-fluid w-75"/>
</header>
<Container>
<ul>
<p>{item.title}</p>
</ul>
</Container>
</div>
);
}
}
export default myitem;
I hope you can help me with that, thanks!
UPDATE:
I'm creating a WebApp using ReactJS Library with "npx create-react-app".

appbar responsive with options with react router v4, material-ui and apollo client

I'm working with apollo client, react, reac routerv4 and material-ui, my app is working ,
before insert material-ui i had
<Link to="/" className="navbar">React + GraphQL Tutorial</Link>
then i've inserted material-ui
<AppBar
title="Title"
iconClassNameRight="muidocs-icon-navigation-expand-more"
/>
but it's not clear for me how to add links for the title and options, in responsive mode with small screen the options i think must be invisible, in small screen not.
The official material-ui site is not well explained by example like bootstrap, so i need a litlle of help.
the full code is:
import React, { Component } from 'react';
import {
BrowserRouter,
Link,
Route,
Switch,
} from 'react-router-dom';
import './App.css';
import ChannelsListWithData from './components/ChannelsListWithData';
import NotFound from './components/NotFound';
import ChannelDetails from './components/ChannelDetails';
import AppBar from 'material-ui/AppBar';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import {
ApolloClient,
ApolloProvider,
createNetworkInterface,
toIdValue,
} from 'react-apollo';
const networkInterface = createNetworkInterface({ uri: 'http://localhost:4000/graphql' });
networkInterface.use([{
applyMiddleware(req, next) {
setTimeout(next, 500);
},
}]);
function dataIdFromObject (result) {
if (result.__typename) {
if (result.id !== undefined) {
return `${result.__typename}:${result.id}`;
}
}
return null;
}
// customResolvers:
// This custom resolver tells Apollo Client to check its cache for a Channel object with ID $channelId
// whenever we make a channel query. If it finds a channel with that ID in the cache,
// it will not make a request to the server.
const client = new ApolloClient({
networkInterface,
customResolvers: {
Query: {
channel: (_, args) => {
return toIdValue(dataIdFromObject({ __typename: 'Channel', id: args['id'] }))
},
},
},
dataIdFromObject,
});
class App extends Component {
render() {
return (
<ApolloProvider client={client}>
<BrowserRouter>
<MuiThemeProvider muiTheme={getMuiTheme()}>
<div className="App">
<Link to="/" className="navbar">React + GraphQL Tutorial</Link>
<AppBar
title="Title"
iconClassNameRight="muidocs-icon-navigation-expand-more"
/>
<Switch>
<Route exact path="/" component={ChannelsListWithData}/>
<Route path="/channel/:channelId" component={ChannelDetails}/>
<Route component={ NotFound }/>
</Switch>
</div>
</MuiThemeProvider>
</BrowserRouter>
</ApolloProvider>
);
}
}
export default App;
the right is add a code like this:
<AppBar position="static">
<Toolbar>
<IconButton color="contrast" aria-label="Menu">
</IconButton>
<Typography type="title" color="inherit" >
{"Admin"}
</Typography>
<AuthLink to="/customers" label="Customers"/>
<AuthLink to="/tours" label="Tours"/>
<AuthLink to="/signout" label="Sign Out"/>
<AuthLink to="/signin" label=" Sign In" whenLogged="false"/>
</Toolbar>
</AppBar>
Authlink is just a component that I wrote to show the options and where simple I add the Title to display options.
const AuthLink = (props) => {
let auth = checkAuth();
return (
( (auth && !props.whenLogged ) || (!auth && props.whenLogged == "false") ) ? (
<Link to={props.to} className="navbar"><Button>{props.label}</Button></Link>
) : (
null
)
);
}
"Button" is a component from material, "Link" from react-router, here the imports:
import {
BrowserRouter,
Link,
Route,
Switch,
Redirect,
} from 'react-router-dom';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import IconButton from 'material-ui/IconButton';