Confusion with shared variables in React - reactjs

The "Bad button" only works once, since it's not controlling the same "value" as the "Good button". What am I missing here?
const Test = () => {
const [value, setValue] = useState(0)
const [view, setView] = useState()
const add = () => setValue(value + 1)
const badButton = () => {
return (
<div>
<button onClick={add}>Bad button</button>
</div>
)
}
return (
<div>
{value}
<button onClick={add}>Good button</button>
{view}
<button onClick={() => setView(badButton)}>show bad button</button>
</div>
)
}
Thanks for replying, I'm going to use the flag method as suggested. But I would still like to know why the two buttons don't work the same way in this original case.

Check this sandbox
I feel it's the right way to handle such a usecase. Instead of storing component itself in state. I replaced it with a boolean. By default it will be false and badButton will be hidden, on click of showBadButton, i'm setting the view state true and bad button will come into picture. Actually Its a good buton now. Check it out.

I would use view as a flag to show/hide BadButton component, I have created a demo that showcase the following code snippet:
import React, { useState } from 'react';
import { render } from 'react-dom';
import './style.css';
const Test = () => {
const [value, setValue] = useState(0)
const [view, setView] = useState(false)
const add = () => setValue(value + 1)
const BadButton = () => {
return (
<button onClick={add}>Bad button</button>
)
}
return (
<>
{value}
<button onClick={add}>Good button</button>
{view ? BadButton() : null}
<button onClick={() => setView(!view)}>
{view ? 'hide' : 'show'} bad button
</button>
</>
)
}
render(<Test />, document.getElementById('root'));
Welcome to StackOverflow

Related

There are two buttons and you need to change them alternately

I have two buttons. I can change its color by clicking on one button. And when you click on another button, change its color as well, and return the old color to the first button. Something like toggle. How can I implement such functionality in a react applicatio.
const [toggle, setToggle] = useState(false);
const toggleIt = () => {
setToggle(!toggle);
};
return (
<div>
<button onClick={toggleIt}>Button1</button>
<button onClick={toggleIt}>Button2</button>
)
somthing like this (codesandbox),
import classNames from "classnames";
import { useCallback, useState } from "react";
import "./styles.css";
export default function App() {
const [toggle, setToggle] = useState(false);
const toggleIt = useCallback(() => {
setToggle((toggle) => !toggle);
}, []);
return (
<div>
<button
onClick={toggleIt}
className={classNames({
"btn-act": toggle
})}
>
Btn A
</button>
<button
onClick={toggleIt}
className={classNames({
"btn-act": !toggle
})}
>
Btn B
</button>
</div>
);
}
const [toggle, setToggle] = useState(false);
const toggleIt = () => {
setToggle(!toggle);
};
return (
<div>
<button onClick={toggleIt} style={toggle ? {color: "blue"} : {color: "red"}}</button>
<button onClick={toggleIt} style={toggle ? {color: "pink"} : {color: "purple"}}</button>
</div>
)
Background
You can use the useEffect() hook to accomplish this feature depending on the button pressed. Just hold two states and flip them each time a different button is pressed, and with those two states you can use two separate functions to handle the onClick()'s.
The useEffect() hook automatically re-renders the component once any of the items in the dependency array at the end change, which will happen depending on the button pressed.
You can also directly set true/false values on your state variables with the second value that returns from useState(), and those state variables will automatically have their states updated without you manually assigning them.
There is very likely a better, more efficient way of doing it, but this is just a general guideline, if you will.
This is the code
const [toggleOne, setToggleOne] = useState(false);
const [toggleTwo, setToggleTwo] = useState(true);
const toggleFirst = () => {
setToggleOne(true);
setToggleTwo(false);
};
const toggleSecond = () => {
setToggleOne(false);
setToggleTwo(true);
};
useEffect(() => {
if (toggleOne) {
// Do something with first button pressed
} else if (toggleTwo) {
// Do something with second button pressed
}
}, [toggleOne, toggleTwo]);
return (
<div>
<button onClick={toggleFirst}>Button1</button>
<button onClick={toggleSecond}>Button2</button>
</div>
);

How to add multiple events in one tag?

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;

React State remains immutable when i try to show component onClick

I have button with onClick function like this :
<button className="btn" onClick={(e) => handleClick(user._id, e)} >Edit</button>
const [show, setShow] = useState(false)
const handleClick = (id, e) => {
e.preventDefault()
setShow(!show)
dispatch(getUser(id))}
/* And here rendering based on State */
{
show ? renderUserData() : null
}
So, problem is that setShow(!show) inside the handleClick function does not work and state of show remains false, immutable. if handleClick function contains only setShow(!show) then this function working and toggling renderUserData(), but when it contains both dispatch(getUser(id)) and setShow(!show), state of show remains false all time,please help
try to remove the e.preventDefault() you can play around with your own data but the e.preventDefault() is not useful in buttons (if you have a form try to put it in the onSubmit of the form) but the final solution must look something like this:
import React, { useState } from "react";
export default function App() {
const [show, setShow] = useState(false);
const handleClick = (id, e) => {
setShow(!show);
};
return (
<>
{show ? <h1>Data showed</h1> : null}
<button className="btn" onClick={(e) => handleClick(e)}>
Edit
</button>
</>
);
}

import and export may only appear at the top level - reactjs

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>
);
};

How to use Switch case in React js functional component inside return efficiently by reusing?

I want to use Switch case in React js functional component.
I want an efficient way of using it.
I have this code snippet:
import React, { useState } from 'react';
import FormUserDetails from './FormUserDetails';
function UserForm() {
const [step, setStep] = useState(1);
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const nextStep = () => {
setStep(prevState => prevState + 1)
}
const previousStep = () => {
setStep(prevState => prevState - 1)
}
switch (step) {
case 1:
return (
<div>
<FormUserDetails
/>
<button onClick={() => nextStep()}>
next
</button>
<button onClick={() => previousStep()}>
previous
</button>
</div>
)
case 2:
return (
<div>
<h1>{step}</h1>
<button onClick={() => nextStep()}>
next
</button>
<button onClick={() => previousStep()}>
previous
</button>
</div>
)
default:
return (
<div>
<h1>Final</h1>
</div>
)
}
}
export default UserForm
This code is working fine.
However, in the return
<button onClick={() => nextStep()}>
next
</button>
<button onClick={() => previousStep()}>
previous
</button>
I am repeating this code. I just want to know an efficient code structure to reuse these lines with every switch case.
You can apply a little more code refactoring, factoring the buttons into a reusable component.
const StepButtons = () => (
<Fragment>
<button onClick={nextStep}>next</button>
<button onClick={previousStep}>previous</button>
</Fragment>
);
Result
import React, { Fragment, useState } from 'react';
import FormUserDetails from './FormUserDetails';
function UserForm() {
const [step, setStep] = useState(1);
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const nextStep = () => {
setStep(prevState => prevState + 1);
};
const previousStep = () => {
setStep(prevState => prevState - 1);
};
const StepButtons = () => (
<Fragment>
<button onClick={nextStep}>next</button>
<button onClick={previousStep}>previous</button>
</Fragment>
);
switch (step) {
case 1:
return (
<div>
<FormUserDetails />
<StepButtons />
</div>
);
case 2:
return (
<div>
<h1>{step}</h1>
<StepButtons />
</div>
);
default:
return (
<div>
<h1>Final</h1>
</div>
);
}
}
export default UserForm
You can create a new component in a different file (if you want to distinguish this component of course)
import React from 'react'
export default function NavigationButtons(props) {
return (
<>
<button onClick={props.nextStep}>
next
</button>
<button onClick={props.previousStep}>
previous
</button>
</>
)}
and then use it like this
<NavigationButtons nextStep={nextStep} previousStep={previousStep}/>

Resources