The onClick on the unodered list is not working? - javascript

The on onclick function which should call the function which is HTML inside Java-script (JSX). Does not seems to work??
Does onClick only works on a button or does it also work on the lists too?
class Top extends React.Component{
constructor(){
super();
this.searchjsx = this.searchjsx.bind(this);
}
searchjsx = () =>{
return(
<div id='searchdiv'>
<form id='searchform'>
<input type="text" id="input" name="search"></input>
</form>
</div>
);
}
render(){
return(
<div>
<div id="navbar">
<ul id="nav">
<li><a className="a" href='https://www.google.com/'>Home</a></li>
<li><a className="b" href='https://www.google.com/'>Profile</a></li>
<li><a className="c" href='https://www.google.com/'>Pricing</a></li>
<li onClick={this.searchjsx} id='sch'>Search..</li>
</ul>
</div>
<div>
</div>
</div>
);
}
}

The below worked for me:
import React from "react";
export default class Top extends React.Component {
state = {
showForm: false
};
searchjsx = () => {
console.log("Toggled showForm");
this.setState({ showForm: !this.state.showForm });
};
render() {
return (
<div>
<div id="navbar">
<ul id="nav">
<li>
<a className="a" href="https://www.google.com/">
Home
</a>
</li>
<li>
<a className="b" href="https://www.google.com/">
Profile
</a>
</li>
<li>
<a className="c" href="https://www.google.com/">
Pricing
</a>
</li>
<li onClick={this.searchjsx} id="sch">
Search..
</li>
{this.state.showForm ? (
<div id="searchdiv">
<form id="searchform">
<input type="text" id="input" name="search"></input>
</form>
</div>
) : (
""
)}
</ul>
</div>
<div></div>
</div>
);
}
}
Notes:
onclick should work on any element
You were trying to insert the form inside the onClick attribute. Instead, you should change the state of the component when li is clicked and based on the state show or hide the form
You don't seem to need a constructor in this example

import React from "react";
export default class Top extends React.Component{
state = {
show:false
}
showInput() {
return(
<div id='searchdiv'>
<form id='searchform'>
<input type="text" id="input" name="search"></input>
</form>
</div>
);
}
handleShow() {
this.setState({
show: !this.state.show
})
}
render(){
return(
<div>
<div id="navbar">
<ul id="nav">
<li><a className="a" href='https://www.google.com/'>Home</a></li>
<li><a className="b" href='https://www.google.com/'>Profile</a></li>
<li><a className="c" href='https://www.google.com/'>Pricing</a></li>
<li onClick={e => this.handleShow(e)} id='sch'>Search..</li>
{
this.state.show ? this.showInput() : null
}
</ul>
</div>
</div>
);
}
}
You have to maintain a state variable that can control when to display a component. In this case, show.

Related

Why does adding useState result in a white screen in my react app?

The code below works completely fine and results in the image below.
import React from "react";
import "./App.css";
import { useState } from "react";
function App(){
return(
<body>
<div className="nav_bar">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"></link>
<ul className="top">
<div className="circle circle1">
<li className="material-icons noselect">
drag_handle
</li>
</div>
<div className="circle circle2">
<li className="material-icons noselect">
home
</li>
</div>
<div className="circle circle3">
<li className="material-icons noselect">
person_outline
</li>
</div>
</ul>
<nav>
<ul className="bottom">
<li className="material-icons noselect" id="feed-bottom">
drag_handle
</li>
<li className="material-icons noselect" id="home-bottom">
home
</li>
<li className="material-icons noselect" id="profile-bottom">
person_outline
</li>
</ul>
</nav>
</div>
</body>
);
}
export default App;
Result
Adding useState to get and set the current state causes the navbar to disappear and show a completely white screen. Specifically I am using useState to change the icon shown in the nav bar to text and to set the currernt state to the icon that is clicked. Code Below
import React from "react";
import "./App.css";
import { useState } from "react";
function App(){
const[selected, setselected] = useState('home');
if(selected === 'feed'){
const feed = document.getElementById('feed-bottom');
feed.innerHTML = 'FEED';
} else if (selected === 'profile') {
const profile = document.getElementById('profile-bottom');
profile.innerHTML = 'PROFILE';
}else{
const home = document.getElementById('home-bottom');
home.innerHTML = 'HOME';
}
return(
<body>
<div className="nav_bar">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"></link>
<ul className="top">
<div className="circle circle1">
<li className="material-icons noselect">
drag_handle
</li>
</div>
<div className="circle circle2">
<li className="material-icons noselect">
home
</li>
</div>
<div className="circle circle3">
<li className="material-icons noselect">
person_outline
</li>
</div>
</ul>
<nav>
<ul className="bottom">
<li className="material-icons noselect" id="feed-bottom" onClick={setselected('profile')}>
drag_handle
</li>
<li className="material-icons noselect" id="home-bottom" onClick={setselected('home')}>
home
</li>
<li className="material-icons noselect" id="profile-bottom" onClick={setselected('profile')}>
person_outline
</li>
</ul>
</nav>
</div>
</body>
);
}
export default App;
I've looked up many post that refernece similar issues but couldn't find one that pretained to mine. I would grealty appreciate some assitance.
This line
home.innerHTML = 'HOME';
will cause an error on mount, because on mount, the React elements returned from App haven't been returned yet - the container is still empty; the #feed-bottom element doesn't exist yet.
While you could fix it by only assigning if the element actually exists, it would be far better to do it the React way and put the values conditionally into the JSX. Don't use vanilla DOM methods in React unless you absolutely have to.
Another problem is that your listeners - eg onClick={setselected('home')} - run when computed (immediately), because you're invoking the setselected function instead of passing a function as a prop to onClick.
You also probably meant to pass feed in the feed-bottom element (instead of profile).
To implement your logic in the React way, you need something like:
<li className="material-icons noselect" id="feed-bottom" onClick={() => setselected('feed')}>
{ selected === 'feed' ? 'FEED' : 'drag_handle' }
</li>
<li className="material-icons noselect" id="home-bottom" onClick={() => setselected('home')}>
{ selected === 'home' ? 'HOME' : 'home' }
home
</li>
<li className="material-icons noselect" id="profile-bottom" onClick={() => setselected('profile')}>
{ selected === 'profile' ? 'PROFILE' : 'person_outline' }
person_outline
</li>
and remove all of the if(selected === 'feed'){ and the like code from the top.

Add class / remove class from li item in navbar (React)

I am trying to add 'active' class name to clicked navbar item dynamically and remove the 'active' class name from class respectively. I am using bootstrap so 'active' class name change the color of the li item.
class NavBar extends React.Component {
render() {
return (
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">Blog - App</a>
</div>
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>Chat</li>
<li>About</li>
</ul>
</div>
</nav>
);
};
};
export default NavBar
I am new with React, do i need to handle onClick with a function? I will appreciate any idea or code suggestions.
In react you can do it like this:
By passing in a prop which determines the toggle of className.
const NavBar = props => {
return (
<nav className="navbar navbar-inverse">
<div class="container-fluid">
<div className="navbar-header">
<Link className="navbar-brand">Blog - App</Link>
</div>
<ul className="nav navbar-nav">
<li className={props.active ? 'active' : ''}><Link to="/main">Home</Link></li>
<li><Link to="/chat">Chat</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
</div>
</nav>
);
};
export default NavBar
By State
But then in this case wouldn't be appropriate because nothing is going to click it.
import {useState} from 'react';
const NavBar = () => {
const [active, setActive] = useState('');
clickToChange () {
setActive(true);
}
render() {
return (
<nav className="navbar navbar-inverse">
<div class="container-fluid">
<div className="navbar-header">
<Link className="navbar-brand">Blog - App</Link>
</div>
<ul className="nav navbar-nav">
<li className={state.active ? 'active' : ''}><Link to="/main">Home</Link></li>
<li><Link to="/chat">Chat</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
</div>
</nav>
);
};
};
export default NavBar
In your particular use case I'd probably suggest instead detecting the route
See example here:
React Router v4 - How to get current route?
yes, you could use onClick handler, but then again you will have to rehydrate it from the window.location;
class NavBar extends React.Component {
render() {
state = { active : null }
componentDidMount(){
/** you might as well check if location.pathname includes what you are looking
for before just setting it to state, assuming that there wont be anything
extra; skipping that for simplicity*/
this.setState(window.location.pathname);
}
handleClick = (activeLink) => {
this.setState(activeLink);
}
return (
<nav className="navbar navbar-inverse">
<div className="container-fluid">
<div className="navbar-header">
<a className="navbar-brand" href="#">Blog - App</a>
</div>
<ul className="nav navbar-nav">
<li onClick={()=>this.handleClick('/main')} className={`{this.state.active==='/main'? 'active':''}`}>Home</li>
</ul>
</div>
</nav>
);
};
};
export default NavBar
A more graceful implementation would be using a client side routing library like react-router which gives you Link components like NavLink which attaches active classnames automatically.

Maximum update depth exceeded when trying to setState when user clicks

I am trying to When user clicks on list set a state
I have listing in li tag in a loop when user click one of li tag i want to update some state but react throws error.
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested
Here my main piece of code:
class Header extends React.Component{
constructor(props){
super(props);
this.showCatDetail=this.showCatDetail.bind(this);
this.state={
category:[],
clk_category:[],
detail:false
}
}
componentDidMount() {
fetch('http://127.0.0.1:8000/portfolio/create_category/')
.then(response=>response.json())
.then(categoryJson => this.setState({category: categoryJson},()=>{
this.sortCategory()
}))
}
showCatDetail=(e)=>{
e.preventDefault();
this.setState({detail:true,clk_category:JSON.parse(e.currentTarget.getAttribute('data-item'))},()=>{
console.log(this.state.clk_category)
});
};
sortCategory = ()=>{
let sortArray=this.state.category;
let swap;
for (let i=0;i<sortArray.length;i++)
{
for (let j=0;j<sortArray.length;j++){
if(sortArray[i].category_rank>sortArray[j].category_rank){
swap=sortArray[i];
sortArray[i]= sortArray[j];
sortArray[j]=swap;
}
}
}
this.setState({category:sortArray})
};
render(){
let hreflink=null;
let redirect=null;
if (this.state.detail){
redirect=<Redirect to={`/category_project/${this.state.clk_category.id}`}/>
}
return(
<div>
{redirect}
<header id="header">
<div id="trueHeader">
<div className="wrapper">
<div className="container">
<div className="logo">
<a href={hreflink} id="logo">
</a>
</div>
<div className="menu_main">
<div className="navbar yamm navbar-default">
<div className="container">
<div className="navbar-header">
<div className="visibledevice">
<ul className="nav navbar-nav">
<li><a href={hreflink} className="active">
<i className="fa fa-home">
</i> Home</a></li>
</ul>
</div>
</div>
<div className="navbar-collapse collapse pull-right">
<ul className="nav navbar-nav">
<li><a href={hreflink} className="active">
<i className="fa fa-home">
</i> Contact Us</a></li>
{this.state.category.map(cat=>{
return(
<li data-item={JSON.stringify(cat)} onClick={(e)=>this.showCatDetail(e)}><a href={hreflink} >
<i className="fa fa-home">
</i>{cat.category_name}</a></li>
)
})}
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
</div>
)
}
}
I can't figure out what the problem is...
onClick={(e)=>{this.showCatDetail(e)}}
Try this in onclick

Pagination with json-server and React.js

I am trying to paginate JSON data that I am using with JSON server in React. I am currently using splice to break the data up into pages with 10 items per page. To get the data from each splice I have an unordered list where the list items are assigned the data. I actually want to just have pages and a next button rather than have each page listed at the top of the page, but I cant seem to wrap my head around it. I would like to use _page _limit. Any help would be appreciated. Here is the code.
import React, { Component } from 'react';
// added axios to assist with API calls.
import axios from 'axios';
import './App.css';
import Card from './Card.js';
import SearchBar from "./SearchBar.js"
import star from './images/star.svg';
import wars from './images/wars.svg';
class App extends Component {
constructor(props) {
super(props);
this.state = {
people: []
}
}
componentDidMount() {
this.getPeopleData();
}
getPeopleData(search) {
axios.get('http://localhost:3008/people?_start=0&_end=9&q=' + search).then((response) => {
this.setState ({
people: response.data
});
});
}
//1. Using axios and decided to use the slice method rather than the _page _limit from https://github.com/typicode/json-server#slice
limitPerPage (begin, end) {
axios(`http://localhost:3008/people?_start=${begin}&_end=${end}`).then((response) => {
this.setState ({
people: response.data
});
});
}
render() {
return (
<div className='content'>
<div className='logo'>
<img src={star} alt="star-logo" />
<span className='interview-text'>The Interview</span>
<img src={wars} alt="wars-logo" />
</div>
<h2>Cards</h2>
{/* Decided to display the card pages as a list. Each page holds 10 cards */}
<ul className="card-pagination">
<li>
<a onClick={() => this.limitPerPage(0, 9)}>Page 1</a>
</li>
<li>
<a onClick={() => this.limitPerPage(10, 19)}>Page 2</a>
</li>
<li>
<a onClick={() => this.limitPerPage(20, 29)}>Page 3</a>
</li>
<li>
<a onClick={() => this.limitPerPage(30, 39)}>Page 4</a>
</li>
<li>
<a onClick={() => this.limitPerPage(40, 49)}>Page 5</a>
</li>
<li>
<a onClick={() => this.limitPerPage(50, 59)}>Page 6</a>
</li>
<li>
<a onClick={() => this.limitPerPage(60, 69)}>Page 7</a>
</li>
<li>
<a onClick={() => this.limitPerPage(70, 79)}>Page 8</a>
</li>
<li>
<a onClick={() => this.limitPerPage(80, 89)}>Page 9</a>
</li>
</ul>
{this.state.people.map((person) => {
return <Card
key={person.id}
id={person.id}
name={person.name}
imageURL={('http://localhost:3008/' + person.image)}
birthday={person.birth_year}
planetList={this.state.planets}
homeWorld={person.homeworld}
/>
})}
</div>
);
}
}
export default App;
constructor(props) {
super(props);
this.state = {
people: [],
_page_limit: 10,
currentPage: 0
}
}
...
limitPerPage (begin, end, increase) {
axios(`http://localhost:3008/people?_start=${begin}&_end=${end}`).then((response) => {
this.setState ({
people: response.data,
currentPage: this.state.currentPage + increase
});
});
}
_renderLinks() {
var cp = this.state.currentPage
if (cp == 0) {
// show only "Page 1" and "Next"
return (
<ul className="card-pagination">
<li>Page 1</li>
<li><a onClick={() => this.limitPerPage(10, 20, 1)}>Next</a></li>
</ul>
)
} else if (cp < this.state._page_limit - 1) {
// show "Back", "Page X" and "Next"
return (
<ul className="card-pagination">
<li><a onClick={() => this.limitPerPage((cp-1) * 10, cp * 10), -1}>Back</a></li>
<li>Page {(cp + 1}</li>
<li><a onClick={() => this.limitPerPage((cp+1) * 10, (cp+2) * 10, 1}>Next</a></li>
</ul>
)
} else {
// show "Back", "Page X" and "Next"
return (
<ul className="card-pagination">
<li><a onClick={() => this.limitPerPage((cp-1) * 10, cp * 10, -1)}>Back</a></li>
<li>Page {(cp-1)}</li>
</ul>
)
}
}
render() {
var _page_limit = 10
return (
<div className='content'>
<div className='logo'>
<img src={star} alt="star-logo" />
<span className='interview-text'>The Interview</span>
<img src={wars} alt="wars-logo" />
</div>
<h2>Cards</h2>
{this._renderLinks()}
{this.state.people.map((person) => {
return <Card
key={person.id}
id={person.id}
name={person.name}
imageURL={('http://localhost:3008/' + person.image)}
birthday={person.birth_year}
planetList={this.state.planets}
homeWorld={person.homeworld}
/>
})}
</div>
);
}
}
The expression [...Array(_page_limit).keys()] is a shortcut for creating an array of numbers between 0 and (_page_limit - 1), inclusive.

Vue.js multiple v-on:click events

Is there any way to have multiple v-on:click events on the same item?
Im trying to both show/hide toggle a navigation and do a css animation on the item that toggles the navigation.
<template>
<div>
<nav v-if="seen">
<ul>
<li><a href="#front" v-smooth-scroll>forside</a></li>
<li><a href="#services" v-smooth-scroll>ydelser</a></li>
<li><a href="#cases" v-smooth-scroll>cases</a></li>
<li><a href="#contact" v-smooth-scroll>kontakt</a></li>
</ul>
</nav>
<div #click="seen = !seen" #click="setActive" id="burger-container">
<div id="burger">
<span> </span>
<span> </span>
<span> </span>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
seen: false
}
},
methods: {
setActive (event) {
event.target.classList.toggle('open')
}
}
}
</script>
Why don't you just add the second event to the function, like this:
methods: {
setActive (event) {
event.target.classList.toggle('open')
this.seen = !this.seen
}
}

Categories