The display of map function is updating on input change only. Can someone explain why.
Even though I m useEffect refreshing the page on stack change. Its not working. only input field change is updating the display.
import React, { useState, useEffect } from "react";
export default function App() {
const [stack, setStack] = useState([]);
const [values, setvalues] = useState("");
useEffect(() => {
console.log("Refeshed");
}, [stack]);
return (
<div className="App">
<div className="app-left">
<input
className="stack-input"
placeholder="Element"
value={values}
onChange={(e) => {
setvalues(e.target.value);
}}
/>
<button
className="push-btn"
onClick={() => {
stack.push(values);
}}
>
Push
</button>
<button
className="pop-btn"
onClick={() => {
stack.pop();
}}
>
Pop
</button>
</div>
<ul className="app-right">
{stack.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
CodePudding user response:
You need to call setStack
on click
, and use prevState
to update values. Calling setStack
with let useEffect
to recognise the change in state and will re-render the component
setStack(oldStack => [...oldStack, values]); // adding (.push)
To pop
setItems(oldStack => oldStack.slice(0, -1)); // removes last element
CodePudding user response:
That is because React uses shallow comparison when the state changes to take the decision to rerender or not. You always updated the existing array and that avoids rerendering. You need to create a new array for each operation (push or pop).
Following would also work
const { useEffect, useState } = React;
function App() {
const [stack, setStack] = useState([]);
const [values, setvalues] = useState("");
useEffect(() => {
// console.log("Refeshed");
}, [stack]);
const push = (value) => {
setStack((prevStack) => [...prevStack, value]);
};
const pop = () => {
setStack((prevStack) => prevStack.slice(0, prevStack.length - 1));
};
return (
<div className="App">
<div className="app-left">
<input
className="stack-input"
placeholder="Element"
value={values}
onChange={(e) => {
setvalues(e.target.value);
}}
/>
<button
className="push-btn"
onClick={() => {
push(values);
}}
>
Push
</button>
<button
className="pop-btn"
onClick={() => {
pop();
}}
>
Pop
</button>
</div>
<ul className="app-right">
{stack.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
ReactDOM.render(<App/>, document.getElementById("root"))
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>