2

I am having trouble to change the actif value of a certain name. If I click on the tag 'Sport', I would like the 'actif' value in 'Sport' to change to 1 but I am not sure what is the proper way to write it, I have tried many.

const [activeTag, setActivetag] = useState([
        { name: "Music", value: 1, actif: 1 },
        { name: "Sport", value: 2, actif: 0 },
        { name: "VideoGames", value: 3, actif: 0 },
        { name: "Animals", value: 4, actif: 0 },
        { name: "Party", value: 5, actif: 0 },
        { name: "Arts", value: 6, actif: 0 },
        { name: "Movies", value: 7, actif: 0 },
        { name: "Travels", value: 8, actif: 0 },
        { name: "Cooking", value: 9, actif: 0 },
        { name: "Dance", value: 10, actif: 0 },
    ]);

Thanks in advance!

3 Answers 3

3

You can do something like this on Click event:

var newArr = [... activeTag]; 
newArr[index] = your_newvalue
setActiveTag(newArr);

Updated, I think this one is much better:

 function onClick() {
   setArr(arr.map((x) => (x.name === "Sport" ? { ...x, actif: 1 } : x)));
 }

CodeSandbox

Sign up to request clarification or add additional context in comments.

3 Comments

If you execute this in quickly it can loose state updates, especially if the update depends on the state before that, as in toggling a boolean value
Well, that does not reflect what I suggested, since you are not using the old state it doesnt matter. Try it for yourself, try and toggle (switch true -> false -> true -> ..) the value in state on the button click, it won't work, unless you pass a function to setArr which will use the oldState
You can check it out in my answer, I put the example up of toggling a boolean value in the state
0

I created an example in codesandbox

Basically you want to use the callback in setState and an onChange handler, e.g. with a reduce function

  const onChange = useCallback(
    (name) => () => {
      setActivetag((oldActivetag) =>
        oldActivetag.reduce((acc, current) => {
          let tag = current;
          if (tag.name === name) {
            tag = {
              ...tag,
              actif: !tag.actif
            };
          }
          return [...acc, tag];
        }, [])
      );
    },
    []
  );

and use in render

<button onClick={onChange("Sport")}>Toggle Sport actif</button>

On a side note - One can argue about the usage of useCallback, especially since the dependency array is empty, but for the sake of mentioning it - here it is.

Comments

0

You can pass a callback with previous state to setter. More here.

const UserDiv = () => {
    const [activeTag, setActiveTag] = useState(yourArray);

    const handleClick = event => 
        setActiveTag(prevState =>                 
            prevState.map(el => 
                (el.name != event.target.name) ?
                {...el, actif:0} : 
                {...el, actif: 1}
            )
        )
    
    return (
        yourArray.map(el => 
            <button 
                name={el.name}
                onClick={handleClick}
            >
                {el.value}
            </button>
        )
    )
}

Comments

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.