Home > Net >  Having trouble removing element from state array React/Typescript
Having trouble removing element from state array React/Typescript

Time:11-11

Hello I am having some trouble with removing items from selectedTags state array onClick. Please see the below react component:

TagPosts.tsx

interface Tag {
  id: string;
  name: string;
}

const TagPosts: React.FC= () => {

  let [tags, setTags] = useState<Tag[]>([]);

  let [selectedTags, setSelectedTags] = useState<Tag[]>([]);


  // STATE IS BEING UPDATED FINE WITH THE BELOW addToSelected FUNCTION

  const addToSelected = (tag: Tag) => {
    setSelectedTags([...selectedTags, tag]);
  };

  // HAVING ISSUE WITH REMOVING ITEMS FROM SELECTED ARRAY. STATE IS NOT BEING UPDATED WITH THE BELOW FUNCTION

  const removeFromSelected = (tag: Tag) => {
    const index = selectedTags.indexOf(tag);
    const newSelectedTags = selectedTags;
    newSelectedTags.splice(index, 1);
    setSelectedTags(newSelectedTags);
  };

  const renderTags = tags.map((tag) => {
    if (!selectedTags.includes(tag)) {
      return (
        <StyledTagBox key={tag.id} onClick={() => addToSelected(tag)}>
          <Typography variant="displayTags">{tag.name}</Typography>
        </StyledTagBox>
      );
    } else if (selectedTags.includes(tag)) {
      return (
        <SelectedTagBox key={tag.id} onClick={() => removeFromSelected(tag)}>
          <Typography variant="displayTags" color="#fff">
            {tag.name}
          </Typography>
        </SelectedTagBox>
      );
    }
  });


export default TagPosts;

Can anyone spot the bug? The weird thing is that when i console.log the newSelectedTags variable it is showing the desired array but the setSelectedTags function in the line right after is not executing?

Any help would be greatly appreciated. Thanks!

CodePudding user response:

React's state is immutable, and only checks reference equality.

The problem with your code is splice does not change the state reference.

You can use filter which is very common in React's array update. It will do 2 things:

  • Remove items according to your condition
  • Create a new array that makes React understand state update
  const removeFromSelected = (tag: Tag) => {
    const newSelectedTags = selectedTags.filter(currentTag => currentTag !== tag);
    setSelectedTags(newSelectedTags);
  };

CodePudding user response:

Ah I had this problem plenty of times. The issue is with the rendering of the state.

Since you are copying selectedTags directly using const newSelectedTags = selectedTags;, the state hook thinks that nothing has changed. It is a very annoying feature but should be solved if you instead do something like:

newSelectedTags = [...selectedTags]

(A shallow copy as caTS suggested)

  • Related