if statement doing exact opposite of what I am expecting - javascript

I am sure this is something really easy but for some reason I can't figure out why I am getting the opposite result. If I use the code as below it returns the second if result. If I change it to != null it returns the first if result.
import React from "react";
export default class ListButtons extends React.Component{
render(){
console.log(this.props.before); // null
if(this.props.before == null){
return (
<div>
<ul className="pagination">
<li>
Next
</li>
</ul>
</div>
)
}else{
return (
<div>
<ul className="pagination">
<li>
Previous
</li>
<li>
Next
</li>
</ul>
</div>
)
}
}
}

Try this:
import React from "react";
export default class ListButtons extends React.Component{
render(){
const content = !!this.props.before ? (
<li>
Previous
</li>
<li>
Next
</li>
) : (
<li>
Next
</li>
)
return (
<div>
<ul className="pagination">
{content}
</ul>
</div>
)
}
}
If that doesn't work, it may be an error with where/how this.props.before is set.

Related

Debugging - Self closing tag?

I've spent quite some time trying to find where the missing closing tag is and I'm losing my mind or have gone cross-eyed. All throughout the component I'm getting bugs that say 'Expression Expected' or 'Declaration or statement expected'
I know that I need to close the tags with a '/>/ at the end but I can't find where exactly could be causing the problem.
import { useState } from "react";
import logo from "../icons/logo.svg";
import CSS from "../styles/Navigation.css";
import hamburger from "../icons/icon-hamburger.svg";
import { MobileMenu} from "../components/MobileMenu"
function navigation() {
return (
<div className="navigation">
<img className="logo" src={logo} alt="coffee-roasters-logo" />
<button className="hamburger">
<img src={hamburger} />
</button>
<div className="navigation-menu">
<ul>
<li>
Home
</li>
<li>
About Us
</li>
<li>
Create Your Plan
</li>
</ul>
</>
</div>
)
}
export default navigation;
second last tag change </> to </div> to close one of the earlier divs
function navigation() {
return (
<div className="navigation">
<img className="logo" src={logo} alt="coffee-roasters-logo" />
<button className="hamburger">
<img src={hamburger} />
</button>
<div className="navigation-menu">
<ul>
<li>
Home
</li>
<li>
About Us
</li>
<li>
Create Your Plan
</li>
</ul>
</div>
</div>
);
}

How to change .jsx component style from inside the .js file? React

function Navbar() {
const [shownavcontents, setShownavcontents] = useState(false)
if(shownavcontents){
document.getElementsByClassName("navbardivofmobiledevice").style.display = "none";
}else{
document.getElementsByClassName("navbardivofmobiledevice").style.display = "block";
}
return (
<>
<div className="top">
<Searchbar />
<AiOutlineMenu size={20} className="outlinemenu" onClick={() => {setShownavcontents(true)}} />
</div>
<div className="navbardivofmobiledevice">
<ul>
<li>
Home
</li>
<li>
Members
</li>
<li>
All Posts
</li>
<li>
My Posts
</li>
</ul>
</div>
</>
);
}
As you see I am trying to make responsive navbar, in this case, for mobile devices. I've faced one problem. I've made button on top of navbar and some navbar contents which I want to display only whenever user will click this button and vice versa. So I tried using hooks to check if the user clicked the button which works perfectly, only thing that doesn't works is this if else statements it seems like document.getElementsByClassName("navbardivofmobiledevice").style.display = "none"; doesn't have an effect here. So my question is what is the alternative of this? What can I do here?
This is imperative code:
document.getElementsByClassName("navbardivofmobiledevice").style.display = "none";
With React, you rarely get references to DOM elements and update them manually, and in any case, you do it using Refs, not with the getElement... or querySelector... methods). Instead, you write declarative code and let React take care of the DOM updates for you.
In this case, simply add or remove a hidden attribute or CSS class that has display: none from your JSX:
function Navbar() {
const [shownavcontents, setShownavcontents] = useState(false);
return (
<>
<div className="top">
<Searchbar />
<AiOutlineMenu size={20} className="outlinemenu" onClick={() => {setShownavcontents(true)}} />
</div>
<div className="navbardivofmobiledevice" hidden={ !shownavcontents }>
<ul>
<li>
Home
</li>
<li>
Members
</li>
<li>
All Posts
</li>
<li>
My Posts
</li>
</ul>
</div>
</>
);
}
If you prefer to use a class, assuming you have defined a CSS class .isHidden { display: none; } you would use this line instead:
<div className={ `navbardivofmobiledevice${ shownavcontents ? '' : ' isHidden' }` }>
Regarding what some comments are mentioning about rendering that conditionally like so:
function Navbar() {
const [shownavcontents, setShownavcontents] = useState(false);
return (
<>
<div className="top">
<Searchbar />
<AiOutlineMenu size={20} className="outlinemenu" onClick={() => {setShownavcontents(true)}} />
</div>
{ shownavcontents && (
<div className="navbardivofmobiledevice">
<ul>
<li>
Home
</li>
<li>
Members
</li>
<li>
All Posts
</li>
<li>
My Posts
</li>
</ul>
</div>
) }
</>
);
}
I would avoid that, as hiding your main navigation from Google and other search engines will harm your SEO. You need to hide it visually but still have it in the DOM.
If you want to do better than that, add all the appropriate ARIA attributes and logic for a navigation menu with nested submenus, as explained here:
https://www.w3.org/WAI/ARIA/apg/example-index/menubar/menubar-navigation

Uncaught TypeError: Cannot read properties of undefined (reading 'params') - React

I am not sure what I'm missing here. I did a few search about this error but I can't not find anything that will on my error. The Home screen page will render all images. Prior to this, when a single image is clicked, it will open a new page to show the image. What i was trying to do is, when the image is clicked, i would like the image PLUS the detailed information of the image. All I get is an empty blank page with the error on dev tools (see below). Thank you in advance...
ProductScreen.js:18 Uncaught TypeError: Cannot read properties of undefined (reading 'params')
Here's the code:
import React, { useEffect } from 'react';
import Rating from '../components/Rating';
import { Link, useParams } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';
import { detailsProduct } from '../actions/productActions';
function ProductScreen(props) {
const dispatch = useDispatch();
const { id } = useParams();
console.log("A", id);
const productId = props.match.params.id; // this is the error as per dev tools
console.log(props.match.params.id);
const productDetails = useSelector((state) => state.productDetails);
const { loading, error, product } = productDetails;
useEffect = (() => {
dispatch(detailsProduct(productId));
}, [dispatch, productId]);
return (
//code here
)
}
export default ProductScreen;
[1]: https://i.stack.imgur.com/jdshU.png
Looks like you are not passing the props match while creating the JSX Element of ProductScreen. This line will look like this
<ProductScreen match={someMatchObj} />
As #mushroomator suggests you should also check if the value is undefined.
#mushroomator
This is my JSX...
return (
<div>
{loading ? (
<LoadingBox></LoadingBox>
) : error ? (
<MessageBox variant="danger">{error}</MessageBox>
) : (
<div>
<Link to="/">Back To Result</Link>
<div className="row top">
<div className="col-2">
<img className="large" src={product.image} alt={product.name} ></img>
</div>
<div className="col-1">
<ul>
<li>
<h1>{product.name}</h1>
</li>
<li>
<Rating
rating={product.rating}
numReviews={product.numReviews}
>
</Rating>
</li>
<li>
Price: ${product.price}
</li>
<li>
Description:
<p>{product.description}</p>
</li>
</ul>
</div>
<div className="col-1">
<div className="card card-body">
<ul>
<li>
<div className="row">
<div>Price</div>
<div className="price">${product.price}</div>
</div>
</li>
<li>
<div className="row">
<div>Status</div>
<div>
{product.countInStock > 0 ? (
<span className="success">In Stock</span>
) : (
<span className="danger">Unavailable</span>
)}
</div>
</div>
</li>
<li>
<button className="primary block">Add to Cart</button>
</li>
</ul>
</div>
</div>
</div>
</div>
)}
</div>
)
}
export default ProductScreen;

return value is not rendering when returned from inside the handleclick() function in react

import React from 'react';
import ReactDOM from 'react-dom';
import './home.css';
import {Link} from 'react-router';
class ChangeButton extends React.Component {
/* In this I want that when link one is click button corresponding to that
link should appear */
constructor(props) {
super(props);
this.state = {
arrayofval:[]
};
this.handleClick = this.handleClick.bind(this);
}
componentWillMount(){
this.setState({
arrayofval:[{label:'a',value:'ab'},
{label:'b',value:'bb'},
{label:'c',value:'cb'},
{label:'d',value:'db'},
{label:'e',value:'eb'}
]
})
}
handleClick(index){
if(index===0){
/* this button should appear if the first link is clicked*/
console.log("Come here if first link is clicked ")
return (<div>
<button className="button1">
Connect1
</button>
</div>);
}
else if(index===1)
{
console.log("Come here if second link is clicked ")
return <div>
<button className="button1">
Connect 2
</button>
</div>
}
else if(index===2){
console.log("Come here if 3rd link is clicked ")
return <div>
<button className="button1">
Connect 3
</button>
</div>
}
else if(index===3){
console.log("Come here if 4th link is clicked ")
return <div>
<div className="button1">
Connect 4
</div>
</div>
}
else{
console.log("Come here if 5th link is clicked ")
return <div>
<button className="button1">
Connect 5
</button>
</div>
}
}
render() {
return (
<div>
<div className="col-md-4 col-sm-4 col-xs-4">
<ul className="list-group">
<li className="list-group-item">
<a onClick={()=>this.handleClick(0)} href="#">{this.state.arrayofval[0].label}</a> </li>
<li className="list-group-item"><a onClick={()=>this.handleClick(1)} href="#">{this.state.arrayofval[1].label}</a> </li>
<li className="list-group-item"><a onClick={()=>this.handleClick(2)} href="#">{this.state.arrayofval[2].label}</a> </li>
<li className="list-group-item"><a onClick={()=>this.handleClick(3)} href="#">{this.state.arrayofval[3].label}</a> </li>
<li className="list-group-item"><a onClick={()=>this.handleClick(4)} href="#">{this.state.arrayofval[4].label}</a> </li>
</ul>
</div>
</div>
);
}
}
ReactDOM.render(
<ChangeButton />,
document.getElementById('app')
);
This is the code for displaying button according to the link clicked, so if link one is clicked the button with connect1 should be rendered.I am getting the link and when I am clicking on the link function is calling correct value also but the button is not coming.Suppose I click on the first link I got the console message for that but button has not appeared on the screen.
Return values from event listeners don't render anything. The only time something is rendered is in the render function. Event listeners happen in response to some event, not during the render process.
The way to handle this is would be to have your event listener set some state, and then render based on that:
handleClick(index) {
this.setState({
clicked: index
});
}
--
render() {
return (
<div>
<div className="col-md-4 col-sm-4 col-xs-4">
<ul className="list-group">
<li className="list-group-item">
<a onClick={()=>this.handleClick(0)} href="#">{this.state.arrayofval[0].label}</a>
</li>
<li className="list-group-item">
<a onClick={()=>this.handleClick(1)} href="#">{this.state.arrayofval[1].label}</a>
</li>
<li className="list-group-item">
<a onClick={()=>this.handleClick(2)} href="#">{this.state.arrayofval[2].label}</a>
</li>
<li className="list-group-item">
<a onClick={()=>this.handleClick(3)} href="#">{this.state.arrayofval[3].label}</a>
</li>
<li className="list-group-item">
<a onClick={()=>this.handleClick(4)} href="#">{this.state.arrayofval[4].label}</a>
</li>
</ul>
<div>
<button className="button1">
Connect {this.state.clicked + 1}
</button>
</div>
</div>
</div>
);
}
An even better way would be to use .map on your array:
render() {
return (
<div>
<div className="col-md-4 col-sm-4 col-xs-4">
<ul className="list-group">
{this.state.arrayofval.map((item, i) => (
<li className="list-group-item" key={i}>
<a onClick={() => this.handleClick(i)} href="#">{item.label}</a>
{this.state.clicked === i &&
<button className="button1">
Connect {this.state.clicked + 1}
</button>
}
</li>
))}
</ul>
</div>
</div>
);
}
I've never seen something like a click event returns a component.
You must think different way for best practises and use state I think.
import React from 'react';
import ReactDOM from 'react-dom';
import './home.css';
import {Link} from 'react-router';
class ChangeButton extends React.Component {
/* In this I want that when link one is click button corresponding to that
link should appear */
constructor(props) {
super(props);
this.state = {
arrayofval:[],
clicked: -1
};
this.handleClick = this.handleClick.bind(this);
}
componentWillMount(){
this.setState({
arrayofval:[{label:'a',value:'ab'},
{label:'b',value:'bb'},
{label:'c',value:'cb'},
{label:'d',value:'db'},
{label:'e',value:'eb'}
]
})
}
handleClick(index){
this.setState({clicked: index});
}
render() {
return (
<div>
<div className="col-md-4 col-sm-4 col-xs-4">
<ul className="list-group">
<li className="list-group-item">
<a onClick={()=>this.handleClick(0)} href="#">{this.state.arrayofval[0].label}</a>
{ this.state.clicked === 0 ? <button className="button1">Connect1</button> : null }
</li>
<li className="list-group-item">
<a onClick={()=>this.handleClick(1)} href="#">{this.state.arrayofval[1].label}</a>
{ this.state.clicked === 1 ? <button className="button1">Connect2</button> : null }
</li>
<li className="list-group-item">
<a onClick={()=>this.handleClick(2)} href="#">{this.state.arrayofval[2].label}</a>
{ this.state.clicked === 2 ? <button className="button1">Connect3</button> : null }
</li>
<li className="list-group-item">
<a onClick={()=>this.handleClick(3)} href="#">{this.state.arrayofval[3].label}</a>
{ this.state.clicked === 3 ? <button className="button1">Connect4</button> : null }
</li>
<li className="list-group-item">
<a onClick={()=>this.handleClick(4)} href="#">{this.state.arrayofval[4].label}</a>
{ this.state.clicked === 4 ? <button className="button1">Connect5</button> : null }
</li>
</ul>
</div>
</div>
);
}
}
ReactDOM.render(
<ChangeButton />,
document.getElementById('app')
);
You need a way to change state whenever the handleClick() method is called:
import React from 'react';
import ReactDOM from 'react-dom';
import './home.css';
import {Link} from 'react-router';
class ChangeButton extends React.Component {
/* In this I want that when link one is click button corresponding to that
link should appear */
constructor(props) {
super(props);
this.state = {
arrayofval:[]
index: 0 // this is where I track state change
};
this.handleClick = this.handleClick.bind(this);
}
componentWillMount(){
this.setState({
arrayofval:[{label:'a',value:'ab'},
{label:'b',value:'bb'},
{label:'c',value:'cb'},
{label:'d',value:'db'},
{label:'e',value:'eb'}
]
})
}
handleClick(index){
if(index===0){
/* this button should appear if the first link is clicked*/
console.log("Come here if first link is clicked ")
return (<div>
<button className="button1">
Connect1
</button>
</div>);
// set the index value in any of these conditions
}
else if(index===1)
{
console.log("Come here if second link is clicked ")
return <div>
<button className="button1">
Connect 2
</button>
</div>
}
else if(index===2){
console.log("Come here if 3rd link is clicked ")
return <div>
<button className="button1">
Connect 3
</button>
</div>
}
else if(index===3){
console.log("Come here if 4th link is clicked ")
return <div>
<div className="button1">
Connect 4
</div>
</div>
}
else{
console.log("Come here if 5th link is clicked ")
return <div>
<button className="button1">
Connect 5
</button>
</div>
}
}
render() {
return (
<div>
<div className="col-md-4 col-sm-4 col-xs-4">
<ul className="list-group">
<li className="list-group-item">
<a onClick={()=>this.handleClick(0)} href="#">{this.state.arrayofval[0].label}</a> </li>
<li className="list-group-item"><a onClick={()=>this.handleClick(1)} href="#">{this.state.arrayofval[1].label}</a> </li>
<li className="list-group-item"><a onClick={()=>this.handleClick(2)} href="#">{this.state.arrayofval[2].label}</a> </li>
<li className="list-group-item"><a onClick={()=>this.handleClick(3)} href="#">{this.state.arrayofval[3].label}</a> </li>
<li className="list-group-item"><a onClick={()=>this.handleClick(4)} href="#">{this.state.arrayofval[4].label}</a> </li>
</ul>
</div>
</div>
);
}
}
ReactDOM.render(
<ChangeButton />,
document.getElementById('app')
);
Calling setState() allows the component to re-render.

Converting JavaScript to work with React component

New to React and am trying to write my script in React but not sure how to do it.I've tried using states but that has just clouded me with more confusion. The below code is a sample of something I might commonly create.
Here's my script:
const hamburger = document.querySelector(".hamburger");
hamburger.addEventListener("click", function () {
hamburger.classList.toggle("is-active");
document.querySelector(".navigation").classList.toggle("slide-in");
document.querySelector("body").classList.toggle("menu-active");
document.querySelector(".shell-ui-main").classList.toggle("menu-overlay");
});
Here's a basic react component for a navbar:
import React from 'react';
export default class NavComponent extends React.Component {
render() {
return (
<div className="container">
<button className="hamburger hamburger--squeeze" type="button">
<span className="hamburger-box">
<span className="hamburger-inner"></span>
</span>
</button>
<a className="logo-link" href="/">
<img width="94" height="31" src="/img/logos/logo.png" srcSet="/img/logos/logo.png 1x, /img/logos/logo#2x.png 2x, /img/logos/logo#3x.png 3x"
alt="logo" className="logo" />
</a>
<nav className="navigation">
<ul className="nav">
<li className="single-item">
Home
</li>
<li className="single-item">
Item 2
</li>
<li className="single-item">
Item 3
</li>
<li className="single-item">
Item 4
</li>
</ul>
</nav>
</div>
);
}
}
Here's the solution in case anyone is interested. Additionally I pass the props down to the component and control from there instead of the individual const.
import React from 'react';
const HamburgerToggle = (props) => (
<button className={"hamburger hamburger--squeeze" + (props.active ? " is-active" : "")} onClick={props.clickHandler} type="button">
<span className="hamburger-box">
<span className="hamburger-inner"></span>
</span>
</button>
);
const Logo = () => (
<a className="logo-link" href="/">
<img width="94" height="31" src="/img/logos/logo.png" srcSet="/img/logos/logo.png 1x, /img/logos/logo#2x.png 2x, /img/logos/logo#3x.png 3x" alt="Logo" className="logo" />
</a>
);
const Navigation = (props) => (
<nav className={"navigation" + (props.active ? " slide-in" : "")}>
<ul className="nav">
<li className="single-item">
Home
</li>
<li className="single-item">
intem 2
</li>
<li className="single-item">
item 3
</li>
<li className="single-item">
item 4
</li>
</ul>
</nav>
);
export default class NavComponent extends React.Component {
state = {active: false};
handleClick(e){
this.setState({active: !this.state.active});
console.log(this.state.active);
}
render() {
return (
<div className="container">
<HamburgerToggle active={this.state.active} clickHandler={this.handleClick.bind(this)} />
<Logo />
<Navigation active={this.state.active} clickHandler={this.handleClick.bind(this)} />
</div>
);
}
}

Categories

Resources