I am trying to show or hide a div in Reactjs using the state value in the CSS style option - display and I am using functions with hooks. I have a button and below the button a div. When i click the button i either want to hide or show the contents in the div based on whether it is currently shown or hidden.
This is the basic test code I have
import React, { useState } from "react";
function hide() {
return (
<div>
<Mycomp />
</div>
);
}
function Mycomp() {
const [dp, setDp] = useState("none");
return (
<form>
<button
onClick={() => {
setDp("block");
}}
>
Test
</button>
<div style={{ display: dp }}>Test</div>
</form>
);
}
export default hide;
I then use this hide component in my App.js file. When I click the button the new state is assigned but then the page re-renders and the initial state is loaded again almost immediately. How can I go by ensuring the new state is kept? Eventually I will create a function where if the div display or not based on the previous state.
The issue is that the button is inside a <form>. So any click on that button will submit the form and refresh the page.
Can I make a <button> not submit a form?
You need to add a type="button" to your <button>
import React, { useState } from "react";
function Hide() {
return (
<div>
<Mycomp />
</div>
);
}
function Mycomp() {
const [dp, setDp] = useState(false);
return (
<form>
<button
type="button"
onClick={() => setDp(!dp)}
>
Test
</button>
{dp && <div>Test</div>}
</form>
);
}
export default Hide;
Your code should be something like this, instead of using block and none as style we can use conditional JSX (which is more ideal approach) -:
function Mycomp(){
const[dp, toggleDp] = useState(false);
return(
<form>
<button onClick={()=>{toggleDp(!dp)}}>Test</button>
{dp && <div>Test</div>}
</form>
)
}
export default hide
A better implementation would be to have your state variable TRUE/FALSE value and based on it display the element using a conditional rendering, note e.preventDefault in the button handler to stop the refresh/redirect, here is a working snippet, also a codesandbox:
const { useState, useEffect } = React;
function App() {
return (
<div>
<Mycomp />
</div>
);
}
function Mycomp() {
const [dp, setDp] = useState(true);
return (
<form>
<button
onClick={(e) => {
e.preventDefault();
setDp(!dp);
}}
>
Test
</button>
{dp && <div>Test</div>}
</form>
);
}
ReactDOM.render(<App />, document.getElementById("react-root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>
Related
when I click the particular show more button the content should be displayed, the condition is the whole component should not re-rendering
I have used a useState when I clicked the button it is re-rendering the whole component
it is taking a long time to re-render every div
give an easy solution for this.
const [arr,setmarr] =useState([])
const oncl=(e)=>{
setarr((prev)=>[...prev,e.target.value])
}
return{
divarray.map((i,j)=>{
{console.log("tdic)")}
return(
<Commentbox divarr={arr[j]} value={j} oncl={(e)=>oncl(e) } />
)
}
}
Commentbox component
return
<div>
div{j}
// some icons here
{divarr && <div> right side div </div>}
<button onClick={(e)=>{oncl(e)}} value={j} >see more</button >
</div>
before onClick on showmore
after showmore button has been clicked on the second div
you should change each box to a component to solve this problem.
make that component with class base component because you need getSanpShotBeforeUpadte.
getSanpShotBeforeUpadte: you can control your component's render with this method.dont forget this method will give you nextProps,nextState and snapshot as parameter
class Box extends Component{
state = {
// more
showMore: false,
}
getSnapshotBeforeUpdate(nextProps,nextState){
// OTHER CONDITIONS
if(nextState.showMore !== this.state.showMore) return true
return false
}
render(){
return (
<div>
{/* CODE ... */}
<div style={{display: this.state.showMore ? 'block' : 'none'}}>
HERE IS A TEXT
</div>
<button onClick={()=>this.setState({showMore: !this.state.showMore})}>show more</button>
</div>
)
}
}
Struggling to get my modal rendering when I click a button to show it. Here is the flow of this functionality
We start off by triggering toggle when the start coding button is clicked:
Start Coding
</button>
<StartModal
isShowing={isShowing}
hide={toggle}
/>
toggle is passed down from useModal()
const { isShowing, toggle } = useModal();
userModal changes the state of isShowing to true/false
import { useState } from 'react';
const useModal = () => {
const[isShowing, setIsShowing] = useState(false);
function toggle() {
console.log('toggle is being triggered')
setIsShowing(!isShowing);
}
return {
isShowing,
toggle,
};
};
export default useModal;
At this point toggle is being triggered is console logged
StartModal then should become visible:
import React from "react";
import "../../assets/scss/modal.scss"
import ReactDOM from 'react-dom';
const StartModal = ({ isShowing, hide }) => isShowing ? ReactDOM.createPortal(
<>
<div className="md-modal md-effect-12">
<div className="md-content">
<h3>Ready to start programming?</h3>
<div>
<p>The session will be split into 5 phases:</p>
<ul>
<li>Introductions</li>
<li>Pseudo-Code</li>
<li>Time to Code</li>
<li>Solution</li>
<li>Rating</li>
</ul>
<button
className="md-close"
onClick={hide}
>Close</button>
</div>
</div>
</div>
<div className="md-overlay"></div>
</>, document.body
) : null;
export default StartModal;
When I click the start coding button, my modal appears in my HTML. When I check the Elements tab on my browser, I see the modal showing up but cannot see it on my screen. I don't think it is a css problem because I have a z-index: 2000 property on the parent div. It seems as though the div appears outside of my react components?
I think the best approach is to use it with a new div.
For example:
<body>
<div id="root"></div>
<div id="modal"></div>
</body>
so you can look it here: https://codesandbox.io/s/affectionate-banzai-xypu3i
I'm trying to create a simple app where if you click on a button, a modal overlay appears, and if you click on the 'x' in the modal it disappears.
I made a component for my button, called ShowOffer, and I have an onclick on it which toggles the boolean value of modalVisible, which is a piece of state.
However, nothing happens when I click on it.
I made another button element with the same onclick, and it seems to work fine.
Here is a code sandbox
You are adding onClick on the ShowOffer component, but here you are just passing it as a prop in it.
<ShowOffer display={"block"} onClick={toggleVisibility} />
is same as
React.createElement(ShowOffer, {
display: "block",
onClick: toggleVisibility
});
Under the hook, you are just passing an argument to a function
You have to add onClick event on the button in ShowOffer component as:
Live Demo
<button
style={{ display: `${display}` }}
onClick={toggleVisibility}
className="show-offer"
>
Show Offer
</button>
and you have to pass the toggleVisibility callback to ShowOffer as:
<ShowOffer display={"block"} toggleVisibility={toggleVisibility} />
This is the simple logic. Your ShowOffer component is not identify the onclick event and this component's button is not have any event handlers. So you just pass the event or directly pass the function name for access the event. Passing props name is the important one.
<ShowOffer display={"block"} onClick = {toggleBox}/>
export default function ShowOffer({ display, onClick}) {
return (
<button style={{ display: `${display}` }} className="show-offer" onClick={onClick}>
Show Offer
</button>
);
}
or
<ShowOffer display={"block"} toggleBoxFunct = {toggleBox}/>
export default function ShowOffer({ display, toggleBoxFunct }) {
return (
<button style={{ display: `${display}` }} className="show-offer" onClick={toggleBoxFunct}>
Show Offer
</button>
);
}
You can use concept of Callbacks,
App.js, make following changes,
pass toggleVisibility={toggleVisibility} as props, no need to mention onClick at component but at button
return (
<div className="App">
<Modal display={modalVisible ? "flex" : "none"} />
<ShowOffer display={"block"} onClick={toggleVisibility} toggleVisibility={toggleVisibility}/>
<button onClick={toggleVisibility}>Button</button>
</div>
);
ShowOffer.js, props passed function, call that function here with onclick,
import React from "react";
import "./ShowOffer.css";
export default function ShowOffer({ display, toggleVisibility }) {
return (
<button style={{ display: `${display}` }} onClick={toggleVisibility} className="show-offer">
Show Offer
</button>
);
}
working solution is here, https://codesandbox.io/embed/modal-overlay-tnis9?fontsize=14&hidenavigation=1&theme=dark
I have a button and for testing purposes, I want to write to the console the index of an array element. More specifically, I have a button in button.js, and that button is displayed on each array element in the IncomeOutputList array. When clicked on, I want each button to print to the console the index of the corresponding IncomeOutputList array element.
For example, by clicking on the button of the second element shown in the image below, I want the console to display index 1 (the first element is the topmost rectangle, which is a blank array element).
Here is a picture of an array element with the button, the button appears while hovering above the number for each array element:
Currently when the page renders, all of the indices of the array are displayed in console, not sure why.
I hope I made my question clear!
button.js:
import React from 'react';
const Button = ({buttonType, handler}) => (
<>
<div className="item__delete">
<button className={buttonType} onClick={handler}>
<i className="ion-ios-close-outline"></i>
</button>
</div>
</>
)
export default Button;
ValueOutput.js:
import React from 'react';
import Button from '../buttons/Button';
//move item__value element to left when hovering over it, and make delete button appear
const ValueOutput = ({type, value, handleClick}) => {
return (
<>
<div className="right clearfix">
<div className="item__value">{type} {value}</div>
<Button buttonType="item__delete--btn" handler={handleClick}/>
</div>
</>
)
}
export default ValueOutput;
IncomeOutput.js:
import React from 'react';
import ValueOutput from './ValueOutput';
const IncomeOutput = ({ desc, type,id, value, handleButton }) => {
//id = inc-{id}
return (
<>
<div className="item clearfix income" id={id}>
<div className="item__description">{desc}</div>
<ValueOutput
type={type}
value={value}
handleClick={handleButton}
/>
</div>
</>
)
}
export default IncomeOutput;
IncomeOutputList.js:
import React from 'react';
import IncomeOutput from './IncomeOutput';
// list will be list of income objects
const IncomeOutputList = ({ list }) => {
const handler = (i) => {
console.log(i);
console.log('the test');
}
return (
<div className="income__list">
<div className="income__list--title">INCOME</div>
{list.map((item, index) => <IncomeOutput
id={item.id}
value={item.incomeValue}
type={item.budgetType}
desc={item.desc}
handleButton={handler(index)}
/>
)}
</div>
)
}
You are passing handler(index) as your event handler. Since that doesn't return anything you are effectively passing undefined as your handler. You will want to change your handler method to return a function:
const handler = (i) => {
return () => {
console.log(i);
console.log('the test');
};
};
You could also just wrap your call to handler in a function, buttonHandle={() => handler(index)} - This is effectively the same thing.
The problem is that the handler function is executed right away when the code is encountered.
Whenever you have () the function will execute right away when encountered. It is not waiting for the event to fire.
Here is what you can do:
handleButton={() => handler(index)}
I'm new to React, Nodejs and JavaScript so bear with me.
I'm doing some practice with onClick events to change text by clicking some buttons, I have an input type="checkbox" to make the text bold when checked and vise versa, 2 buttons to increase and decrease the text size by 1+ or 1- and a span that shows the current text size (16 is my default), and finally a span with the id="textSpan" that have the text meant to be modified. I also want this buttons, the checkbox and the span with the id="fontSizeSpan" that shows the current font size to be hidden by default and when you click the text it appears on its left.
This is the code so far:
class FontChooser extends React.Component {
constructor(props) {
super(props);
this.state = {hidden: true};
this.checkInput = React.createRef();
this.hide = React.createRef();
}
toggle(){
this.setState({hidden: !this.state.hidden});
this.hide.current
}
makeBold(){
this.setState({bold: !this.state.bold});
this.checkInput.current
}
changeSize(){
this.setState({size: !this.props.size})
for(var i = this.props.size; i <= this.props.max; i++);
}
render() {
return(
<div>
<input type="checkbox" id="boldCheckbox" ref={this.hide} hidden={false} onClick={this.makeBold.bind(this)}/>
<button id="decreaseButton" ref={this.hide} hidden={false}>-</button>
<span id="fontSizeSpan" ref={this.hide} hidden={false}>{this.props.size}</span>
<button id="increaseButton" ref={this.hide} hidden={false} onClick={this.changeSize.bind(this)}>+</button>
<span id="textSpan" ref={this.checkInput} onClick={this.toggle.bind(this)}>{this.props.text}</span>
</div>
);
}
right now their hidden attribute is false so I can see them.Here's the html which is not much:
<div id='container'></div>
<script type="text/jsx">
ReactDOM.render(
<div>
<FontChooser min='4' max='40' size='16' text='You can change me!' bold='false'/>
</div>,
document.getElementById('container'))
;
</script>
So far all I have managed is for the browser console(I'm using Firefox react component addon) to confirm there is a functioning event that doesn't really work, as in when I click the text, the buttons or the input checkbox the props does change to false or true every click but that's about it.
I appreciate it if someone could guide me through this.
NOTE:
just in case nothing is imported, also I setup a local server with Nodejs
Here is an Example of what you want: https://codesandbox.io/s/mystifying-cookies-v7w3l?file=/src/App.js
Basically, I have 4 variables: text, fontWeight, fontSize and showTools.
Each button has its own task and also you can select if show or not.
In React you don't have to care about ids like in older frameworks. You can generate the elements just in the place where you are with the information which you need. So, basically, we have the 4 variables and use them wisely where we want (as styles props, as text and even as a conditional to show components). It's the magic of React and JSX.
In the code I've use hooks, part of the latest definition of React. For that my Components is functional and not a Class. it makes it easier and faster for examples and prototyping.
The tools are show by default just to let you play with it
import React from "react";
import "./styles.css";
export default function App() {
const [text, setText] = React.useState("");
const [boldFont, setBoldFont] = React.useState(false);
const [fontSize, setFontSize] = React.useState(14);
const [showTools, setShowTools] = React.useState(true);
return (
<div className="App">
<div
style={{
fontWeight: boldFont ? "bold" : "normal",
fontSize: `${fontSize}px`
}}
>
<span onClick={() => setShowTools(!showTools)}>
{text || "Text Example"}
</span>
</div>
{showTools && (
<div>
<button onClick={() => setBoldFont(!boldFont)}>Bold</button> |
<button onClick={() => setFontSize(fontSize + 1)}>A+</button>
<button onClick={() => setFontSize(fontSize - 1)}>a-</button>
<input
type="text"
value={text}
onChange={event => {
setText(event.target.value);
}}
/>
</div>
)}
</div>
);
}