2

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

0

5 Answers 5

2

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);
  };
Sign up to request clarification or add additional context in comments.

1 Comment

@yongchang, can you please mark this as the answer if it solved your problem?
0

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.

1 Comment

i did....click on the same link on my question. i have call the setTest and nothing happens
0

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.

Comments

0

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

Comments

0

There are 2 issues with your code

  1. you are mutating the state with test.unshift
  2. you do not use the setTest

try

  const onChange = () => {
    console.log("onChange");
    const updatedTest = [...test];
    updatedTest.unshift("4");
    setTest(updatedTest);
  };

1 Comment

@giorgimoniava fair point, updated code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.