I am new to React. I have a simple page with buttons which increase the count by 1 or decrease by 1. The solution shows the right way which is by using inline functions for the minus button.However when I changed the plus button to use a regular function, I am getting too many re render.
import React, { useState } from 'react'
import randomColor from 'randomcolor'
export default function Playground() {
const [count, setCount] = useState(0)
const add = (n) =>{
setCount(n+1);
};
return (
<div>
{count}
<button onClick={() => add(count)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
</div>
)
}
<button onClick={add(count)}>+</button> immediately triggers add function when the component render.
Try this:
import React, { useState } from 'react'
import randomColor from 'randomcolor'
export default function Playground() {
const [count, setCount] = useState(0)
const add = () =>{
setCount(count+1);
};
return (
<div>
{count}
<button onClick={() => add()}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
</div>
)
}
You can use regular function or arrow function. But in your case, you were calling the add function every time it re-renders. Consider the difference in the following vanilla JavaScript code snippets:
function add() {
console.log("Add");
}
document.getElementById("Button").addEventListener("click", add);
vs
function add() {
console.log("Add");
}
document.getElementById("Button").addEventListener("click", add()); //<--
The first one is the way to go.
In the React world, the following implementations are all valid:
function ButtonWithArrowFunction() {
const handleClick = () => {
console.log("Clicked");
};
return <button onClick={handleClick}>Press Me</button>;
}
function ButtonWithInlineArrowFunction() {
return (
<button
onClick={() => {
console.log("Clicked");
}}
>
Press Me
</button>
);
}
function ButtonWithRegularFunction() {
function handleClick() {
console.log("Clicked");
}
return <button onClick={handleClick}>Press Me</button>;
}
function ButtonWithInlineRegularFunction() {
return (
<button
onClick={function handleClick() {
console.log("Clicked");
}}
>
Press Me
</button>
);
}
function ButtonWithHigherOrderFunction() {
function createHandleClickFunction() {
return function handleClick() {
console.log("Clicked");
};
}
return <button onClick={createHandleClickFunction()}>Press Me</button>;
}
you can not pass add() because it will execute the funcition and will trigger an infinite cycle. Just pass the reference add of the method, so it will execute only on the click event
import React, { useState} from 'react'
const App = () => {
const [count, setCount] = useState(0);
const add = (n) =>{
setCount(count+1);
}
return (
<div>
{count}
<button onClick={add}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
</div>
)
}
export default App;
Related
I tried any workaround I can think ,
but still cant remove EventListener .
here are all my ways of thinking
I cant think of any other way to solve it .
hope someone can tell me what can i do
delete directly
function doSomething(){}
const [testP, setTestP] = useState();
useEffect(() => { setTestP(document.querySelector("#test")); }, [testP]);
function App(){
return(
<>
<p id="test"></p>
<button onClick={ testP.addEventListener("click",doSomething); }></button>
<button onClick={ testP.removeEventListener("click",doSomething); }></button>
< />
);
}
use one useEffect() hook
function doSomething(){}
const [testP, setTestP] = useState();
useEffect(() => { setTestP(document.querySelector("#test")); }, [testP]);
const [do, setDo] = useState(false);
useEffect(() => {
if(do === true) testP.addEventListener("click", doSomething);
else testP.removeEventListener("click", doSomething);
}, [do]);
function App(){
return(
<>
<p id="test"></p>
<button onClick={ setDo(true); }></button>
<button onClick={ setDo(false); }></button>
< />
);
}
use two useEffect() hook
function doSomething(){}
const [testP, setTestP] = useState();
useEffect(() => { setTestP(document.querySelector("#test")); }, [testP]);
const [enable, setEnable] = useState(true);
const [disable, setDisable] = useState(true);
useEffect(() => { testP.addEventListener("click", doSomething); }, [enable]);
useEffect(() => { testP.removeEventListener("click", doSomething); }, [disable]);
function App(){
return(
<>
<p id="test"></p>
<button onClick={ setEnable(!enable); }></button>
<button onClick={ setDisable(!disable); }></button>
< />
);
}
use useState hook
function doSomething(){}
const [foo, setFoo] = useState();
function App(){
return(
<>
<p id="test" onClick={foo}></p>
<button onClick={ setFoo(doSomething); }></button>
<button onClick={ setFoo(null); }></button>
< />
);
}
As far as I understand you are trying to add and remove Event listener on p by clicking on buttons. So If you want to do that then you can simply make use of useRef hook, there is no need of using useState or useEffect. You can take the ref of p using useRef and simply attach eventListener or detach event listener by clicking on buttons.
CODESANDBOX LINK
import { useRef } from "react";
export default function Comp() {
const pRef = useRef(null);
function doSomething() {
console.log("Loggin from doSomething");
}
function attachEventListener() {
if (pRef.current) pRef.current.addEventListener("click", doSomething);
}
function detachEventListener() {
if (pRef.current) pRef.current.removeEventListener("click", doSomething);
}
return (
<>
<p id="test" ref={pRef}>
paragraph
</p>
<button onClick={attachEventListener}>addEventListener</button>
<button onClick={detachEventListener}>removeEventListener</button>
</>
);
}
You have to pass a function to onClick instead you are invoking it.
<button onClick={ setFoo(doSomething); }></button>
So above snippet should be
<button onClick={ () => setFoo(doSomething) }></button>
I would suggest using controlled component
function doSomething() {
console.log('Do something')
}
export function App(props) {
const [enabled, setEnabled] = React.useState(false)
return (
<div className='App'>
<p onClick={enabled ? doSomething : null}>paragraph</p>
<button onClick={() => setEnabled(true)}>Add event</button>
<button onClick={() => setEnabled(false)}>Remove event</button>
</div>
);
}
I want to dynamically add component every time a button is clicked. But I can't figure it out myself, and most answers I found online are class based.
This is what I wrote: I want to pass a component and a name props every time the button is clicked.
import List from "./List";
function App() {
let listCount = 0;
const extraList = () => {
listCount++;
return(
<List name={`list-{listCount}`} />
);
};
return (
<div>
<button onClick={extraList}>Add List</button>
</div>
);
}
export default App;
You can use useState
function App() {
const [listCount, setListCount] = useState(0);
const extraList = () => {
setListCount(listCount + 1);
};
return (
<div>
{Array.from({ length: listCount }, (_, i) => i + 1).map((i) => (
<List name={`list-${i}`} />
))}
<button onClick={extraList}>Add List</button>
</div>
);
}
I'm making a counting timer which is described below with this react functional component
import {useEffect, useState, useRef} from 'react'
function Content() {
const [countdown, setCountdown] = useState(10)
const [show, setShow] = useState(true)
const ref = useRef()
function handleStart() {
ref.current = setInterval(() => {
setCountdown(prev => prev - 1)
}, 1000)
}
function handleStop() {
clearInterval(ref.current)
}
return (
<div>
<h2 style={{padding: 20}}>Time remaining: {countdown}</h2>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
)
}
export default Content;
How do I hide these two buttons after clicking one of the two.
Assuming show is the variable to control whether the buttons are visible or not.
<div>
<h2 style={{padding: 20}}>Time remaining: {countdown}</h2>
{show && <>
<button onClick={() => {
setShow(false)
handleStart()
}}>Start</button>
<button onClick={() => {
setShow(false)
handleStop()
}}>Stop</button>
</>}
</div>
React children need to return one element, so you can either wrap it in a div, or an empty element, <> </>, so you can return multiple nodes without adding a div, span, etc.
show && <></> means if show is true, the right-hand side will render, otherwise, it won't be rendered.
First, you have to introduce new state variable, you need one ror the start btn and another for the stop btn.
You have to setShow to false on either click and render the buttons conditionally depending on show variable:
const [countdown, setCountdown] = useState(10)
const [showStart, setShowStart] = useState(true)
const [showStop, setShowStop] = useState(true);
const ref = useRef()
function handleStart() {
setShowStart(false);
ref.current = setInterval(() => {
setCountdown(prev => prev - 1)
}, 1000)
}
function handleStop() {
setShowStop(false);
clearInterval(ref.current)
}
return (
<div>
<h2 style={{padding: 20}}>Time remaining: {countdown}</h2>
{showStart && <button onClick={handleStart}>Start</button>}
{showStop && <button onClick={handleStop}>Stop</button>}
</div>
)
Hope the Below Code Solver Your Problem
import React, { useEffect, useState, useRef } from 'react';
function Example() {
const [countdown, setCountdown] = useState(10);
const [show, setShow] = useState(true);
const ref = useRef();
function handleStart() {
setShow(!show);
ref.current = setInterval(() => {
setCountdown((prev) => prev - 1);
}, 1000);
}
function handleStop() {
setShow(!show);
clearInterval(ref.current);
}
return (
<div>
<h2 style={{ padding: 20 }}>Time remaining: {countdown}</h2>
{show && (
<div>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
)}
</div>
);
}
export default Example;
To show my question here is a Demo code.(I'm using React Hooks and Antd.)
My Question is:
when currId state is changed and I click MyButton the state is still '' (which is the initial state). onClick event is an arrow function and in it is showModal with params, if there's no params currId can be seen changed but now with params state isn't changed. May I ask what is the reason of it and how I can get changed currId in showModal?
(operation: click 'Change CurrId' button --> setCurrId('12345') ---> click 'MyButton' ---> console.log(currId))
import React, { useState } from 'react'
import 'antd/dist/antd.css';
import { Button} from 'antd';
const MyComponent= () => {
const [currId, setCurrId] = useState('');
const changeCurrId= async () => {
setCurrSolutionId('12345');
}
const showModal = async (num:any) => {
console.log("☆ currid:");// I cannot get the currId state '12345' but ''
console.log(currId);
console.log("☆ num:");//I can get the num params 5
console.log(num);
};
return (
<>
<Button type="primary" onClick={changeCurrId}>Change CurrId</Button>
<Button type="primary" onClick={() => {showModal(5)}}>MyButton</Button>
</>
);
}
const MyComponent= () => {
const [currId, setCurrId] = useState('');
const changeCurrId= () => {
setCurrId('12345');
}
const showModal = (num:string) => {
console.log("☆ currid:");
console.log(num);
};
const changeCurrentIdAndShowModal = (id : string) => {
setCurrId(id);
showModal(id)
console.log("☆ id:");
console.log(id);
};
return (
<>
<Button type="primary" onClick={() => changeCurrId()}>MyButton</Button>
<Button type="primary" onClick={() => showModal('5')}>MyButton</Button>
<Button type="primary" onClick={() => changeCurrentIdAndShowModal('12345')}>MyButton</Button>
</>
);
}
Is this the intention you want?
Good day Everyone,
I'm trying to run a query that increases a number whenever a button is clicked. I'm using a course from udemy is kinda old and our setup/installation is different. Please look at my code down below.
let count = 0;
const addOne = () => {
count++;
rendertheCounterApp();
};
const minus =() => {
console.log('Minus',);
}
const Reset = () => {
console.log ('Reset');
};
const rendertheCounterApp = () => {
const App = () => {
return (
<div className='App'>
<h1>Toggler {count} </h1>
<button onClick ={addOne}> +1 </button>
<button onClick={minus}>-1</button>
<button onClick ={Reset}>Rest</button>
</div>
);
};
export default App;
};
rendertheCounterApp();
is there any way I can modify that code to make the number increase whenever I click on the button?
Thanks in advance.
You need to have state to store the count and you can increase or decrease the count without creating any special functions. Try something like:
import React, { useState } from 'react';
const RenderTheCounterApp = () => {
const [count, setCount] = React.useState(0);
return (
<div>
<h1>count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Add</button>
<button onClick={() => setCount(count - 1)}>Subtract</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
};