0

I'm quite new to React. I have been learning this for a couple of months. I'm currently creating tags using ant-design and trying to removing them on click. I have a state of users and depending on whether they want to remove or create a tag the user state is updated. However, when the I remove the tag the users state doesn't update immediately and returns empty array when I console.log(users); in the removeUser() . I have looked a previous questions similar to this however they utilise useEffect() but this not suitable for my use case. I have also tried putting this <Tag> in the return part of the code which sort of solves the problem however the colour of the tags keeps re-rendering every time I check a checkbox from the table of users. When the tag is removed the removeUser() function is called where is parse the userId so I can remove the user from the state. However, because the state isn't updated it won't remove it since it's empty so the [...users].map() doesn't map through anything. How do I resolve this?


const [users, setUsers] = useState([]);

const createUserTags = () => {
  const oldUsers = [...users];
  let updatedUsers = selectedRowKeys.map(userId => ( 
  <Tag onClose = {() => removeUser(userId)}
    closable key = {userId}> 
    {[...dataSource].map(user => {
    return user.Id === userId && "{user.firstName}" + " "+"{user.surname}";
      })
    } 
  </Tag>
  ));
  updatedUsers.unshift(oldUsers);
  setUsers([...updatedUsers]);
};

  const removeUser = userId => {
   
        // remove user from array list
       
   };


return (
  <>
    <Button 
      shape = "round"
      onClick = {() => createUserTagsHandler()}
      type = "primary"> Create Tag 
    </Button> 
</>
  </>
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

3 Answers3

1

It is because setting state is an asynchronous function and when you call the console.log the setting state function isn't complete thus giving previous state value . Please refer for detailed understanding .

NeERAJ TK
  • 2,447
  • 1
  • 11
  • 25
1

The state seems to lag behind by one step when you console.log it because setState() is asynchronous, however, as in a previous case, it still gets updated properly. If this submits to the form you'd see it sends the correct updated state

Tobiju
  • 21
  • 1
  • 4
  • 2
    I've tried using the form however it causes the page to be reloaded and due to my routing its takes it to the homepage. To prevent this I used ```event.preventDefault()``` however this brings me back to my original problem. –  Feb 24 '21 at 15:49
1

setState actions are asynchronous and are batched for performance gains. This is explained in the documentation of setState

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

If you need to ensure ordering of events after a setState call is made, you can pass a callback function. this.setState({ something: true }, () => console.log(this.state))

danhuong
  • 202
  • 1
  • 8