I am using Gatsby with the CSS framework Bulma, In order for the Mobile navbar to work, you have to add an event listener for a button that only becomes available when to screens size is a certain dimension. in previous versions of Gatsby, it worked fine, only in the recent week have I been running to problems. Now I get an Invalid hook call
import { Link } from 'gatsby'
let Header = () => {
useEffect(() => {
let burger = document.getElementById(`burger`);
let menu = document.getElementById(`navMenu`)
burger.addEventListener(`click`, function () {
burger.classList.toggle(`is-active`);
menu.classList.toggle(`is-active`)
})
});
return (
<>
<nav className="navbar is-fixed-top" id="navbar">
<div className="navbar-brand">
<Link to="/">
<p className="navbar-item">CMJR DEVELOPMENT</p>
</Link>
<a role="button" id="burger" className="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div className="navbar-menu" id="navMenu">
<div className="navbar-end">
<Link to={"/service"} className="navbar-item ">Services</Link>
<Link to={"/portfolio"} className="navbar-item ">Portfolio</Link>
<Link to={"/contact"} className="navbar-item ">Contact</Link>
</div>
</div>
</nav>
</>
)
}
export default Header;
I know I'm doing something wrong, just not what.
Related
I'm trying to make my navbar sticky when it gets to a certain section of my website but my intersectionObserverApi isn't working. I think it has something to do with my useRefs being null when I try to select the section element I want to observe.I have tried selecting them using querySelector but didn't work either.
This is in React btw any help would be appreciated.
Here is my component:
import { React, useRef } from "react";
import "./About.css";
import Image from "../Images/7F1E6503-0880-4C1A-B2E8-070D0FAE543B.jpg";
const About = () => {
const aboutSectionRef = useRef("");
console.log(aboutSectionRef); // getting object with key value pair of current: ''
const el = aboutSectionRef.current;
console.log(el); // I'm getting null in the console.log
function stickyNavBar(entries, observer) {
console.log(entries);
}
document.addEventListener("DOMContentLoaded", function () {
const sectionObserver = new IntersectionObserver(stickyNavBar, {
root: null,
threshold: 0.1,
});
sectionObserver.observe(el);
});
// const aboutSectionRef = useRef(null);
// document.addEventListener(
// "DOMContentLoaded",
//
// );
return (
<section
ref={aboutSectionRef}
id="about-section"
className="about-section aboutsectionref"
>
<img className="headshot" src={Image} alt="pic of Osman" />
<h1>Nice to meet you</h1>
<p>
Over the past 2 years I have embarked on a journey that has undoubtedly
<span className="blue"> challenged</span> me like never before when I
decided to start
<span className="blue"> learning</span> how to code. I am a{" "}
<span className="blue"> self-taught</span> web developer with{" "}
<span className="blue"> passion</span> and{" "}
<span className="blue"> determination</span> for anything I set my mind
to.
</p>
<h2>Attributes I bring to the team</h2>
<div className="two-uls">
<ul>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Open-Minded
</li>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Team Player
</li>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Drive to
self-improve
</li>
</ul>
<ul>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Time Management
</li>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Communication
</li>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Attention to
detail
</li>
</ul>
</div>
</section>
);
};
export default About;
I am trying to get the height of the header element using Jquery's height() method. But it gives NAN when I console the values
Here's my react snippet
import React, { Component } from "react";
import $ from 'jquery'; //un-used
export default class HomepageNavigationBar extends Component {
render() {
return (
<header className="header_area">
<div className="main_menu">
<nav className="navbar navbar-expand-lg navbar-light">
<div className="container">
<a className="navbar-brand logo_h" href="index.html">
<img src="img/logo.png" alt="" />
</a>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="icon-bar" /> <span className="icon-bar" />
<span className="icon-bar" />
</button>
.
.
.
//dots used to denote that code further exists but to make this minimal I have removed them.
</div>
</header>
);
}
}
and here's my external theme.js file
(function($) {
"use strict";
var nav_offset_top = $("header").height() + 50;
console.log(nav_offset_top); //gives 'NAN' when console, even after I scroll
function navbarFixed() {
if ($(".header_area").length) {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= nav_offset_top) {
alert('Hi');
$(".header_area").addClass("navbar_fixed");
} else {
alert('no Hi');
$(".header_area").removeClass("navbar_fixed");
}
});
}
}
navbarFixed();
})(jQuery);
Problems are:
1)
console.log(nav_offset_top);
this above code gives NAN when console the value even after I scroll the page up and down
2)
$(".header_area").length
header_area length is always 0 even after I scroll up and down the page
Can someone here help me out?
I believe you're getting NaN because you're accessing header when it is not yet rendered.
Put your code in componentDidMount() instead to make sure that elements are rendered before accessing it.
Read more: https://reactjs.org/docs/react-component.html#componentdidmount
The docs state that:
Initialization that requires DOM nodes should go here.
This is exactly what you're doing, accessing DOM nodes using jQuery.
class HomepageNavigationBar extends React.Component {
componentDidMount() {
var nav_offset_top = $("header").height() + 50;
console.log(nav_offset_top);
function navbarFixed() {
if ($(".header_area").length) {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= nav_offset_top) {
alert('Hi');
$(".header_area").addClass("navbar_fixed");
} else {
alert('no Hi');
$(".header_area").removeClass("navbar_fixed");
}
});
}
}
navbarFixed();
}
render() {
return (
<header className="header_area">
<div className="main_menu">
<nav className="navbar navbar-expand-lg navbar-light">
<div className="container">
<a className="navbar-brand logo_h" href="index.html">
<img src="img/logo.png" alt="" />
</a>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="icon-bar" /> <span className="icon-bar" />
<span className="icon-bar" />
</button>
</div>
</nav>
</div>
</header>
);
}
}
ReactDOM.render(<HomepageNavigationBar />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" style="height: 1000px;"></div>
This is my first proper Vue JS project...I've searched Stack O and can't find anything that specifically addresses my issue, but I apologise if this has already been asked.
The Problem
I have two components, the parent is the page layout, while the child is a module of that page. When somebody clicks on a button in the child component, I want to trigger a function in the parent component.
The $emit part of the process is firing correctly according to the VueJS Dev Tools, but the function in the parent doesn't trigger.
Where am I going wrong?
Here is my abberviated code (I've removed anything not related to the issue)...
Parent Component
<template>
<div :toggle-nav="showHideNav" :class="navState">
<div class="wrapper">
<layout-toolbar></layout-toolbar>
</div>
</div>
</template>
<script>
import layoutToolbar from '~/components/layout/toolbar.vue'
export default {
components: {
layoutToolbar,
},
data: function() {
return {
navState: 'menu-closed'
}
},
methods: {
showHideNav: function(event) {
if (this.navState == 'menu-closed') {
this.navState = 'menu-open'
} else {
this.navState = 'menu-closed'
}
}
}
}
</script>
Child Component
<template>
<div class="toolbar" role="navigation">
<div class="tools" role="group">
<button
class="button-icon"
aria-label="Open Navigation"
#click="$emit('toggle-nav')">
<i aria-hidden="true" class="far fa-bars" title="Open Navigation"></i>
<span class="sr-only">Open Navigation</span>
</button>
</div>
</div>
</template>
Do I need to be making use of props?
Appreciate any help that can be offered.
You have to pass a function as a prop and then emit that function from your child component. So your parent template looks like this .
<template>
<div :toggle-nav="showHideNav" :class="navState">
<div class="wrapper">
<layout-toolbar #showHideNav="showHideNav"></layout-toolbar>
</div>
</div>
</template>
And your child template looks like this
<template>
<div class="toolbar" role="navigation">
<div class="tools" role="group">
<button
class="button-icon"
aria-label="Open Navigation"
#click="$emit('showHideNav',<pass-your-event-or-data>)">
<i aria-hidden="true" class="far fa-bars" title="Open Navigation"></i>
<span class="sr-only">Open Navigation</span>
</button>
</div>
</div>
</template>
I am trying to change state of the component and render it to page.
var navbarValue = [{"Category":"Home","Status":1},{"Category":"About","Status":0},{"Category":"Contact","Status":0}];
class NavbarList extends React.Component {
constructor() {
super();
this.onClick = this.handleClick.bind(this);
}
handleClick(event) {
const {id} = event.target;
console.log(id);
if(!navbarValue[id].Status){
{navbarValue.map((obj, index) =>{
if(navbarValue[index].Status){
navbarValue[index].Status = 0;
return <li key={index}><a id={index} onClick={this.onClick}>{obj.Category} </a></li>
}
})}
navbarValue[id].Status = 1;
return <li className="active" key={id}><a id={id} onClick={this.onClick}>{navbarValue[id].Category}</a></li>
}
}
render() {
return (
<div className="navbar-wrapper">
<div className="container">
<nav className="navbar navbar-fixed-static-top navbar-inverse">
<div className="container">
<div className="navbar-header">
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span className="sr-only">Toggle navigation</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<a className="navbar-brand" href="#">BrandName</a>
</div>
<div id="navbar" className="collapse navbar-collapse">
<ul className="nav navbar-nav">
{navbarValue.map((obj, index) => {
if (obj.Status)
return <li className="active" key={index}><a id={index} onClick={this.onClick}>{obj.Category}</a></li>
return <li key={index}><a id={index} onClick={this.onClick}>{obj.Category} </a></li>
})}
</ul>
</div>
</div>
</nav>
</div>
</div>
)};
};
ReactDOM.render(
<NavbarList />,
document.getElementById('root')
);
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
I have an if statement in handleClick(event) which validates if function has to be run and rerender elements.
First it checks if button which is already active is not being clicked. Next if statment is in loop to find previous active element, change objects property to 0 and render to not active.
At the end render new active element to active and set objects property to 1.
Put navbarValue in a state object and update the state onClick. You don't need if/else statements here. Because your components will be rerendered on state update.
Like this: https://stackoverflow.com/a/45134876/4953199
How can I display a glyphicon in a bootstrap navbar? I have a React.js project that I have been working on, and I would like to relocate the GitHub glyphicon to the navbar. So far I have something looking like the below.
The code pertaining to the navbar in the App.js
import React, {PropTypes} from 'react';
import NavBar from './common/NavBar-test';
import FontAwesome from 'react-fontawesome';
var navbar = {};
navbar.brand = {linkTo: "#", text: "app"};
navbar.links = [
{linkTo: "#Demonstration", text: "Demonstration"},
{linkTo: "#Demonstration2", text: "Demonstration #2"},
{linkTo: "https://github.com/user/app", text:"GitHub Source Code"},
{linkTo: "https://itunes.apple.com/us/app/", text: "App Store"},
{linkTo: "https://github.com/user/appr", text: "The Future of app"}
];
And Navbar-test.js
import React, { PropTypes } from 'react';
// create classes
var NavBar = React.createClass({
render: function(){
return(
<nav className="navbar navbar-default navbar-static-top">
<div className="container-fluid">
<div className="navbar-header">
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false">
<span className="sr-only">Toggle navigation</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<NavBrand linkTo={this.props.brand.linkTo} text={this.props.brand.text} />
</div>
<div className="collapse navbar-collapse" id="navbar-collapse">
<NavMenu links={this.props.links} />
</div>
</div>
</nav>
);
}
});
var NavBrand = React.createClass({
render: function(){
return (
<a className="navbar-brand" href={this.props.linkTo}>{this.props.text}</a>
);
}
});
var NavMenu = React.createClass({
render: function(){
var links = this.props.links.map(function(link){
if(link.dropdown) {
return (
<NavLinkDropdown key={link.text} links={link.links} text={link.text} active={link.active} icon={link.icon} />
);
}
else {
return (
<NavLink key={link.text} linkTo={link.linkTo} text={link.text} active={link.active} />
);
}
});
return (
<ul className="nav navbar-nav">
{links}
</ul>
);
}
});
var NavLinkDropdown = React.createClass({
render: function(){
var active = false;
var links = this.props.links.map(function(link){
if(link.active){
active = true;
}
return (
<NavLink key={link.text} linkTo={link.linkTo} text={link.text} active={link.active} />
);
});
return (
<li className={"dropdown " + (active ? "active" : "")}>
<a href="#" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
{this.props.text}
<span className="caret"></span>
</a>
<ul className="dropdown-menu">
{links}
</ul>
</li>
);
}
});
var NavLink = React.createClass({
render: function(){
return(
<li className={(this.props.active ? "active" : "")}>
<a href={this.props.linkTo}>{this.props.text}{this.props.icon}</a>
</li>
);
}
});
export default NavBar;
Ideally, I'd like to place the GitHub glyphicon in front of the text that states GitHub Source Code.
It looks like you are mapping over the links (which is cool), but you can add your desired GitHub data before the mapped links.
You might end up with something like this:
<span>
<NavLink>GitHub Source Code</NavLink>
<GlyphIcon />
</span>
// Then map over links here
In short, I finally got the glyphicons to display how I would like them to.
I needed to modify the source of the Navbar-test to support icons.
Something like,
class NavMenu extends React.Component {
render() {
var links = this.props.links.map(function(link){
if(link.dropdown) {
return (
<NavLinkDropdown key={link.text} links={link.links} text={link.text} active={link.active} icon={link.icon} />
);
}
else {
return (
<NavLink key={link.text} linkTo={link.linkTo} icon={link.icon} text={link.text} active={link.active} />
);
}
});
return (
<ul className="nav navbar-nav">
{links}
</ul>
); // close return
} // close render
} // close NavMenu