Adam
Adam

Reputation: 2552

Unable to add values to array state React

I recently posted a question with regards to sending and receiving data via a websocket. In the interest of not duplicating most of the work, the original question is found here: Socket.io emitting undefined variable React

I have since modified my app slightly so that each id received from the server gets added or removed to a disabled array (if the focus parameter received from the server is true, add the id and if not, remove it). This is so that I can disabled/enable questions based off the focus sent.

The slight adjustments I've made are three fold, all within the App.js file

1. Add disabled array to state

const [disabled, setDisabled] = useState([])

2. Include disabled parameter to the question

<TextArea
    cols={50}
    helperText="Optional helper text here; if message is more than one line text should wrap (~100 character count maximum)"
    id="text2"
    invalidText="Invalid error message."
    labelText="Text area label"
    placeholder="Placeholder text"
    rows={4}
    onFocus={() => setFocusTrue('text2')}
    onBlur={() => setFocusFalse('text2')}
    disabled={disabled.indexOf('text2')!==-1}
/>

You will note in the above that the disabled parameter will be set to true if the questionId is included in the disabled array (therefore disabling the question) and false if not

3. Add questionId to disabled state array

useEffect(() => {
    socket.on("message", ({ user, id, focus }) => {
        console.log(user, "clicked on", id, "with focus", focus)
        console.log('adding', id, 'to disabled')
        setDisabled(prevDisabled => [...prevDisabled, id]);
        console.log("disabled:", disabled)
    })
}, [])

For now, I am just adding all the questionIds coming from the server to the disabled array so I can test whether they are indeed getting added. But this is my issue in that the disabled array is always empty (see screenshot below). The id variable exists as can be seen in the console log output that precedes setting the new disabled state, but it is not getting added as expected.

enter image description here

EDIT: As per the comments, I can see that the disabled array is in fact getting updated, if I console.log(disabled) just before rendering. However, if I apply any sort of logic to the array, I get an error. The below is the modified useEffect which contains some logic (essentially, to add or remove an id to the array)

useEffect(() => {
    socket.on("message", ({ user, id, focus }) => {
      console.log(user, "clicked on", id, "with focus", focus)
      console.log('adding', id, 'to disabled')
      if (focus) {
        console.log('not my user and focus is true')
        setDisabled(prevDisabled => [...prevDisabled, id])
        console.log("disabled after adding", disabled)
      } else {
        let filteredArray = disabled.filter(idToRemove => idToRemove !== id)
        setDisabled({disabled: filteredArray});
      }
      console.log("disabled:", disabled)
    })
  }, [])

When I click on a textbox, the id of the question gets added to the disabled array as expected, but when I click out of it, I get the following error:

disabled.indexOf is not a function

This referring to disabled={disabled.indexOf('text1')!==-1}

Upvotes: 0

Views: 132

Answers (1)

Kalhan.Toress
Kalhan.Toress

Reputation: 21901

I think your code is fine, if you are trying to console.log the most resent state right after you setting it, it won't work why? setState is asynchronous it might not work real time as you expected.

what you actually want to try is add a useEffect and listen for changes of the disabled state

useEffect(() => {
    console.log("disabled", disabled);
}, [disabled]); // since disabled is in the dependency array this hook function will call, every time when the disabled gets updated.
// so you are so sure the disabled is getting updated correctly

or just do a simple console.log(disabled) right before the render and see.

and your modified version of useEffect is incorrect as I see, it should be corrected as

....
const filteredArray = disabled.filter(idToRemove => idToRemove !== id)
setDisabled(filteredArray);
....

Upvotes: 2

Related Questions