Why React function component call WITHOUT state change - reactjs

here is the code: https://codesandbox.io/s/interesting-mirzakhani-h38g1k
import "./styles.css";
import { useState } from "react";
export default function App() {
const [state, setState] = useState(false);
console.log("executed");
return (
<>
<p>This component renders three (3) times:</p>
<p>1) First time is initial render.</p>
<p>
2) Second time is when clicking the button for the first time to update
state.
</p>
<p>
<strong>
3) Why does is render again when clicking the button second time and
settings the same state again?
</strong>
</p>
<p>Check console.</p>
<pre>state: {String(state)}</pre>
<button onClick={() => setState(true)}>setState(true)</button>
</>
);
}
And the situation here is:
initial (expected)
click the btn first time. State is updated and console. (expected)
click the btn second time, and state didn't change, but console again. (why?)
I found some source code about function dispatchSetState which is actually is setState in the demo. And here is the critical code is shown as the img.
First time click the btn, fiber.lanes === NoLanes is true, and then check the state is equal or not and then decide to update or not (objectIs).
Second time click the btn, fiber.lanes === NoLanes is false, and it just skip the comparison between old state and new state. Then the React start update.
So, what is exactly fiber.lanes is in second time? I found it is 1 which is SyncLane. here is ALL I found in source code.
diagram
I still don't know why react did this.

Related

Changing the React component state with same value on button click trigger re-render for the first two button clicks. Why UI re-rendering twice?

When I click on the 'Rerender UI' button then it prints in the console for the first two clicks. I think it should print in the console only for the first time when I click on the 'Rerender UI' button because on the button click the component state is changed so UI will re-render and the console log will be printed in the console. Why is it printing for the second click? StrictMode is off. See code:
export default function UseCallbackComp() {
const [stateVar, setStateVar] = useState<any>()
console.log("Parent Rerendered!")
return (
<>
<div>UseCallbackComp content</div>
<div>
<button
onClick={() => {
setStateVar(1)
}}
>
Rerender UI
</button>
</div>
</>
)
}
When I put the console log line inside useEffect like below it prints only for the first time 'ReRender UI' button is clicked which is the expected behaviour.
useEffect(() => {
console.log("Parent Rerendered!")
})
From the below two links I got to know whats the behaviour of react when useState is used:
stackoverflow question
gitHub discussion
There are two different cases for which useState behaves differently for same value.
Case 1: When useState used with same value as the initial value.
Result: No rerendering at all.
export default function LifecycleEvents() {
const [stateVar, setStateVar] = useState<any>(0)
console.log("Parent Rerendered!")
return (
<>
<button
onClick={() => {
setStateVar(0) //same value as the initial value
}}
>
Rerender UI
</button>
</>
)
}
Case 2: When useState used with different value first and then with the same value.
Result: First both Parent and child will be re-rendered. But for the second time, only the render function of Parent component will get called, Nothing else.
See code:
export default function LifecycleEvents() {
const [stateVar, setStateVar] = useState<any>(0)
console.log("Parent Rerendered!")
return (
<>
<button
onClick={() => {
setStateVar(1) //different value then initial value.
}}
>
Rerender UI
</button>
</>
)
}
Conclusion: Nothing to worry unless you have an expensive render method of the component. In that case use memo.

Why react function component is behaving strangely?

For example, I have a state and it can be changed by clicking on the buttons. I also have a log to track the rendering and rerendering of the component. When I click on the button and change the state, the log is triggered and everything is fine. But when I click 2 times on the same value, the log fires again. Clicking 3 times does nothing. Please explain what could be the reason
const App = () => {
const [state, setState] = useState(1);
console.log("render");
return (
<div>
<h3>{state}</h3>
<button onClick={() => {setState(1)}}>1</button>
<button onClick={() => {setState(2)}}>2</button>
</div>
);
};
export default App;
React rerenders a component if the state is changing, but in your example, when you click on a button again, the value of state does not change, because you want to change value of 2 to 2, so react does not rerender the component.

React onClick property not firing

I am trying to implement a simple component (an animated hamburger menu button). Its class needs to be updated when it is active or not. For that point, I'm using a state hook.
I want to add a onClick property to this button to invert its state. But this onClick function is never firing.
When I set the button active by myself, the button appearence changes as I wanted.
I am using fullPage.js in my project.
I saw a lot of topic about that, but no one answered to my problem...
Thanks for future answers !
Here is my code :
import React, { useState } from 'react';
import './hamburger.css';
const MenuButton = () => {
const [isMenuActive, setIsMenuActive] = useState(false);
return (
<button className={`hamburger hamburger--slider ${isMenuActive && "is-active"}`} type="button" onClick={() => setIsMenuActive(!isMenuActive)}>
<span className="hamburger-box">
<span className="hamburger-inner"></span>
</span>
</button>
);
};
export default MenuButton;
``
You are starting the state with false value. So it's not firing the onClick event because it's inactive from the get go
change the initial state useState(true)
Ok I found the problem.
I didn't noticed that I was using React v17 (beta). I downgraded to React 16 and my button works well !

React JS - Reset Form Data after Modal Close

I'm trying to reset my form data when a modal closes. I think part of my problem is that the form data <Mint> is in another component.
Honestly, any time the modal is shown or hidden I would like to reset the data.
So if there is a way I can reset the form data inside the toggleModalOne() function that would be awesome, but I can't figure out how.
Any advice is greatly appreciated.
// BuyIt.jsx
import React, { useState } from "react";
import TextLoop from "react-text-loop";
import Modal from "react-modal";
import Mint from "../../components/slider/mint.js";
const BuyIt = () => {
const [isOpen, setIsOpen] = useState(false);
function toggleModalOne() {
setIsOpen(!isOpen);
}
return (
<div className="div-buyNowBtn">
<button id="buyNowBtn" className="white-fill-bg btn-outline btn-lg" onClick={toggleModalOne}>
Buy Now
</button>
</div>
<Modal
isOpen={isOpen}
onRequestClose={toggleModalOne}
contentLabel="My dialog"
className="custom-modal"
overlayClassName="custom-overlay"
closeTimeoutMS={500}
>
<Mint/>
</Modal>
);
}
You could wrap your Modal around a check to see if isOpen is true. This will make the whole modal re-render each time rather than just hiding and showing it but it still being in the DOM (which is what I am assuming is happening).
{ isOpen &&
<Modal
isOpen={isOpen}
onRequestClose={toggleModalOne}
contentLabel="My dialog"
className="custom-modal"
overlayClassName="custom-overlay"
closeTimeoutMS={500}
>
<Mint></Mint>
</Modal>
}
If you want a parent function to reset a child's form state, you probably will want to lift the state up to the parent and pass it down as a prop.

Problem Too many re-renders.Try to render components in connection with a button and state hooks

I'm new to react and face following problem:
I have two buttons and want to render two different components. Pressing one button should set a variable true via state hook and the first component should be shown, on the other side the variable for the other component should be set to false. With this logic I try to render either one or the other component.
With this setup I get following Error Message:
Too many re-renders. React limits the number of renders to prevent an infinite loop.
I guess the solution is simple but I cannot see the why this causes a problem.
Thx for any help!
Here a simplified version of the relevant code:
import { Button } from "semantic-ui-react";
import React, { useState } from "react";
const App = () => {
const [showAggregated, setshowAggregated] = useState(true);
const [showDetailed, setshowDetailed] = useState(false);
return (
<div>
Test
<Button.Group>
<Button
size="mini"
onClick={(() => setshowAggregated(true), setshowDetailed(false))}
>
Aggregated Visualization{" "}
</Button>
<Button.Or />
<Button
size="mini"
onClick={(() => setshowDetailed(true), setshowAggregated(false))}
>
Detailed Visualization
</Button>
</Button.Group>
{/* Second Part of Page if Aggregated Component */}
{showAggregated && <div>Aggregated</div>}
{/* Second Part of Page if Detailed Component */}
{showDetailed && <div>Detailed</div>}
</div>
);
};
export default App;
onClick={(() => setshowDetailed(true), setshowAggregated(false))}
You are using Comma Operator above, which evaluates each of its operands.
In your case you have 2 operands: () => setshowDetailed(true) and setshowAggregated(false), so basically what happens is that each time the component is rendered, the second operand (setshowAggregated(false)) is called, which re-render the component which eventually ends up in an infinite loop.
What you really wanna do is this (an event handler that calls both functions):
onClick={() => {
setshowDetailed(true);
setshowAggregated(false));
}}
Same thing for the second button.

Resources