Reputation: 522
I am trying to add an element into an array after I click the "click me" button. I did a console log to make sure it went inside the function, but despite the function being call, nothing changes.
I also try using useEffect to check if my variable got update
Relevant code:
import React, { useState, useEffect } from "react";
export default function App() {
let [test, setTest] = useState(["1", "2", "3"]);
const onChange = () => {
console.log("onChange");
test.unshift("4");
};
const cards = () => {
return (
<div>
{test.map((item, i) => (
<ul key={i}>
<li>{item}</li>
</ul>
))}
</div>
);
};
useEffect(() => {
console.log("cardData ", test);
}, [test]);
return (
<div className="App">
<button onClick={() => onChange()}>Click me</button>
{cards()}
</div>
);
}
Really need some advice on where did i go wrong
This is my codesandbox link
Upvotes: 2
Views: 1441
Reputation: 13265
The issue is that you directly mutate the test
(test.unshift does mutate the test
instance) and rendering does not happen since no reference change was detected (shallow reference is used when rendering happens).
Try this
const onChange = () => {
console.log("onChange");
const testCopy = [...test];
testCopy.unshift("4");
setTest(testCopy);
};
Code sandbox => https://codesandbox.io/s/dark-wildflower-lkf4u?file=/src/App.js:160-302
Another NOT working case can be given like below due to using the same instance reference (test
).
const onChange = () => {
console.log("onChange");
test.unshift("4");
setTest(test);
};
Upvotes: 2
Reputation: 196306
There are 2 issues with your code
test.unshift
setTest
try
const onChange = () => {
console.log("onChange");
const updatedTest = [...test];
updatedTest.unshift("4");
setTest(updatedTest);
};
Upvotes: 0
Reputation: 2237
It is because you are directly mutating the state, you need to use the useState function hook to update the value of a state variable.
here is my solution https://codesandbox.io/s/determined-perlman-436el?file=/src/App.js:0-727
export default function App() {
let [test, setTest] = useState(["1", "2", "3"]);
const onChange = () => {
console.log("onChange");
setTest(["4", ...test]);
};
const cards = () => {
return (
<div>
{test.map((item, i) => (
<ul key={i}>
<li>{item}</li>
</ul>
))}
</div>
);
};
useEffect(() => {
console.log("cardData ", test);
}, [test]);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={() => onChange()}>Click me</button>
{cards()}
</div>
);
}
Upvotes: 0
Reputation: 2695
You are altering the state test
directly without using setTest
.
Mutating the state directly breaks the primary principle of React's unidirectional data flow, making your app fragile and basically ignoring the whole component lifecycle.
Upgrade your onChange
function as:
const onChange = () => {
console.log("onChange");
setTest([...test, "4"]);
};
Check demo.
Upvotes: 0
Reputation: 751
You are not calling the setTest
function, which is the only thing you should be using to mutate the array test
. Set the new value using setTest
and you should be fine.
Upvotes: 0