I want to hide/show list of elements when I click on button but it won't hide them and console.log of "shouldHide" is equal undefined.
function
showHideToggle(){
this.setState({shouldHide: true});
}
const { shouldHide} = this.props;
Div I want to hide
<div className={shouldHide ? 'hidden' : ''} >
<WeatherInfo />
</div>;
this is the div which is separate from one I'm trying to hide
<div onClick={(e) => {this.List(e);this.showHideToggle}}></div>
constructor
this.state = {
shouldHide: true
};
Your constructor should look like this:
constructor(props) {
super(props);
this.state = { shouldHide: true };
}
and your showhide should probably do this instead otherwise it won't toggle and will always be true
showHideToggle(){
this.setState({shouldHide: this.state.shouldHide ? false : true});
}
const { shouldHide} = this.props; should be const { shouldHide} = this.state in your render area
but <div className={this.state.shouldHide ? 'hidden' : ''} > should work as well given it's in the right area.
Related
I want to have 3 buttons and 3 related components . So that when button click show its related component . Here is my code :
Main Component :
class Main extends Component { constructor(props) {
super(props);
this.state = {
show: false,
}}
onClick(e) {
e.preventDefault()
console.log(e.target.id)
this.setState({ show: !this.state.show }); }
renderTabs() {
var child = this.props.child;
var items = [];
__.forEach(child, (item, index) => {
items.push(
<div>
<Button id={index} onClick={(e) => this.onClick(e)}>{item.data}</Button>
{this.state.show ? (
<CropComponent title={item.data} opts={item.opts} data={item.child} />
) : null}
</div>
);
});
return items;
}
render() {
var opts = this.props.opts;
return (
<div>
{this.renderTabs()}
</div>
)}
}
export default Main;
And here is my CropComponent :
class CropComponent extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div>hello {this.props.data}</div>
);
}
}
export default CropComponent;
Here are my buttons how can i show its related component when click on a button and hide it on re-click the same button ?
Maintain a show state with initial value as -1. Supply event and index to onClick. In onClick do setState of show as index.
Check if show === index and render the corresponding component.
Like this
this.state = {
show: -1
}
onClick(e,index) {
e.preventDefault()
this.setState({ show: show===index? -1 : index});
}
__.forEach(child, (item, index) => {
items.push(
<div>
<Button id={index} onClick={(e) => this.onClick(e,index)}>{item.data}</Button>
{this.state.show === index ? (
<CropComponent title={item.data} opts={item.opts} data={item.child} />
) : null}
</div>
);
});
Edit:
updated the answer based on helpful comment by #Tony Nguyen
When I click on the menu in GeneralNav I successfully switch between true or false.
This menuState once again is passed successfully to Overlay via HomePage.
Though I'm not able to toggle the right classes in Overlay to hide or show the menu. Can someone explain me a correct workflow to add the classes on my EasyFlexCol component to show or hide it? Been stuck for a while now.
Thanks!
class GeneralNav extends Component {
render() {
return (
<div
className="nav-burger-box menu-action"
onClick={this.props.toggleMenu}
>
<div className="nav-burger-top" />
<div className="nav-burger-bottom" />
</div>
);
}
}
class HomePage extends Component {
state = {
showMenu: false
};
toggleMenu = e => {
e.preventDefault();
this.setState(state => ({ showMenu: !state.showMenu }));
};
render() {
return (
<React.Fragment>
<OverlayMenu menuState={this.state.showMenu}/>
<HeaderFullscreen />
</React.Fragment>
);
}
}
class OverlayMenu extends Component {
state = {
showMenu: "overlay-menu-wrapper bg-color-dark overlay-menu-wrapper display-block",
hideMenu: "overlay-menu-wrapper bg-color-dark overlay-menu-wrapper"
};
render() {
let menuState = this.props.menuState
console.log(menuState)
return (
<EasyFlexCol style={"here I want to add the right class to show or hide the overlay menu"}>
</EasyFlexCol>
);
}
}
You can do using ternary operation like this :
i.e if menuState is true show showMenu else vice versa
<EasyFlexCol className={menuState ? showHide.showMenu : showHide.hideMenu}>
</EasyFlexCol>
here is working example for your refrence : https://stackblitz.com/edit/react-wj49ol
Use ternary operator when rendering.
class OverlayMenu extends Component {
render() {
const showHide= { // Assuming that strings below are valid CSS class names
showMenu: "overlay-menu-wrapper bg-color-dark overlay-menu-wrapper display-block",
hideMenu: "overlay-menu-wrapper bg-color-dark overlay-menu-wrapper"
};
let menuState = this.props.menuState
console.log(menuState)
return (
<EasyFlexCol className={menuState ? showHide.showMenu : showHide.hideMenu}>
</EasyFlexCol>
);
}
}
Alternatively you can compose style of <EasyFlexCol/> component dynamically
class OverlayMenu extends Component {
render() {
style={ display: 'block' }
let menuState = this.props.menuState
return (
<EasyFlexCol className={'some-default-class'} style={menuState ? style : {}}>
</EasyFlexCol>
);
}
}
Both example assume that <EasyFlexCol/> has either className property or style property.
I have declared a state called account_type. I have created an onChange event which changes the value of the state upon clicking the div.
<div
className="price-plan"
value="star"
onClick={() => this.setPlan("star")}
>
The issue is that the account_type state does not get updated the first time I click on the div. It only gets updated when I click on it twice. Is there a way to update the state just by clicking the div. Here's an excerpt from my code showing what I am trying to do
let isRedirect = false;
class PricePlan extends React.Component {
constructor(props) {
super(props);
this.state = {
account_type: "",
renderRedirect: false
};
this.handleChange = this.handleChange.bind(this);
}
// Handle fields change
handleChange = input => e => {
this.setState({ [input]: e.target.value });
};
setPlan(plan) {
this.setState({
account_type: plan
});
console.log(this.state.account_type);
// if (this.state.account_type !== undefined) {
// isRedirect = true;
// }
}
render() {
if (isRedirect) {
return (
<Redirect
to={{
pathname: "/sign-up",
state: { step: 2, account_type: this.state.account_type }
}}
/>
);
}
return (
<div
className="price-plan"
value="star"
onClick={() => this.setPlan("star")}
>
<h3>{this.props.planName}</h3>
<div className="mute price-row">Name</div>
<p className="price">Price</p>
<span className="billed-frequency">Cycle</span>
</div>
);
}
}
As #Jayce444 suggests, setState do not immedeately updates state. So setPlan should look like
setPlan(plan) {
this.setState({
account_type: plan
});
console.log(plan); // Don't expect immediate state change in event handler
}
But you can use this.state.account_type anywhere in render() function. And rendering will happen after this.state.account_type is updated on first click.
I have a button that changes the active state onClick:
render() {
return(
<SomeButton
onClick={e => this.handleClick(e)}
id={someId}
activeStatus={someId === this.state.active ? "active" : "not active"}
/>
)
}
The function that changes the state:
handleClick(e) {
e.preventDefault();
this.setState({ active: e.currentTarget.id });
}
The state:
this.state = {
active: null
};
The button that receives the activeStatus props:
export default function SomeButton({ activeStatus }) {
console.log(activeStatus);
return (
// button jsx code
);
}
However, every time I click on the button (I have 3 instances of that button on the page), the activeStatus console.log shows:
I click on button 1:
active
not active
not active
I click on button 2:
active
active
not active
I click on button 3:
active
active
active
I was expecting that the status would toggle depending on the active button which is clicked.
What am I missing?
You can set the state in an array:
this.state = {
active: [false, false, false] // or just: []
};
handleClick(e) {
e.preventDefault();
const activeState = [false, false, false]; // or just: []
activeState[e.currentTarget.index] = true;
// button index ^^
this.setState({ active: activeState });
}
And just pass the activeStatus to the active state:
activeStatus={this.state.active}
Inside your component, bind the active state:
<button className={ activeStatus[0] ? 'active' : 'not-active' }>...</button>
<button className={ activeStatus[1] ? 'active' : 'not-active' }>...</button>
<button className={ activeStatus[2] ? 'active' : 'not-active' }>...</button>
I'd use e.target.id instead of e.currentTarget.id and if the button ids are static, then you could put them into your state and use the id to update a buttonState object (one of several ways to handle it).
Working example: https://codesandbox.io/s/olmn9k08m5
Some notes:
Keep your state consistent (if it's a string, keep it a string, if
it's an array, keep it any array...etc -- in the example below
buttonState is an object and stays an object).
Also, you don't need e.preventDefault() unless you're submitting a
form or trying to block functionality.
Always specify the button's type ("button" or "submit")
ShowButton.js
import React, { Component } from "react";
import SomeButton from "./SomeButton";
const buttons = ["button1", "button2", "button3"];
export default class App extends Component {
state = {
buttonState: {
button1: "inactive",
button2: "inactive",
button3: "inactive"
}
};
handleClick = e => {
const { id } = e.target; // id="button1","button2" or "button3"
this.setState(prevState => ({
buttonState: {
...prevState.buttonState, // spread out object
[id]: prevState.buttonState[id] === "active" ? "inactive" : "active" // use the [id] as an object property (ex: "button1") and set the property's value to "active" or "inactive"
}
}));
};
render = () => (
<div className="container">
<h1>Controlling Active Buttons</h1>
{buttons.map(id => (
<SomeButton
key={id}
id={id}
handleClick={this.handleClick}
activeStatus={this.state.buttonState[id]}
/>
))}
</div>
);
}
SomeButton.js
import React from "react";
export default ({ activeStatus, handleClick, id }) => (
<div style={{ marginBottom: 20 }}>
<button
type="button"
style={{ minWidth: 150 }}
className={`uk-button ${
activeStatus === "active" ? "uk-button-primary" : null
}`}
id={id}
onClick={handleClick}
>
{activeStatus}
</button>
</div>
);
I'm trying to change style when a button is clicked using React. I can see value is changing when button is clicked, but style is not changing. I've been writing in many ways with no luck.
export const Paragraph = () => {
var state = 'none'
const changeState = () => {
state = state == 'none' ? 'inline-block' : 'none'
}
return (
<div>
<p style={{display: state}}</p>
</div>
)
}
Better way to set a class instead inline styles.
class Paragraph extends React.Component{
constructor(){
super();
this.state = {
isClicked: false
};
}
onClick(){
let condition = this.state.isClicked;
this.setState({isClicked: !condition})
}
render(){
return (
<div onClick={this.onClick.bind(this)}>
<p className={this.state.isClicked? "class_1" : "class_2"}></p>
</div>
);
}
}