-1
import React, { useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const [theRoom, setRoom] = useState(null);

  const updateVideoDevice = (e) => {
    console.log("room", theRoom);
  };

  const createRoom = () => {
    console.log("we change the room", theRoom);
    setRoom({
      localparticipants: {}
    });
    console.log("we change the room after", theRoom);
  };

  useEffect(() => {
    const select = document.getElementById("video-devices");
    select.addEventListener("change", updateVideoDevice);
  }, []);
  return (
    <div className="App">
      <select id="video-devices">
        <option value="1">1</option>
        <option value="2">2</option>
      </select>
      <button onClick={createRoom}>change obj</button>
    </div>
  );
}

I have this codebase. When I press the change obj button for the first time it doesn't set theRoom to the object

{
          localparticipants: {}
        }

But when I press the button for the second time it does, and after that, I try to change the select element's options I got null for the console log in the updateVideoDevice function.

How do I solve these two issues with React?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
margherita pizza
  • 6,623
  • 23
  • 84
  • 152
  • Does this answer your question? [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately) – jonrsharpe Nov 30 '20 at 12:14

3 Answers3

0
const [theRoom, setRoom] = useState(null);

setRoom is asynchronous function, so you will not see the change immediately.

Also, you don't need to add event listener to select tag. You can simply use onChange method. So remove all with useEffect and then change the code as below.

<select id="video-devices" onChange={updateVideoDevice}>
michael
  • 4,053
  • 2
  • 12
  • 31
0

you need to chnage how you call the onclick method so it's look like this:

<button onClick={()=>createRoom()}>change obj</button>
TalOrlanczyk
  • 1,205
  • 7
  • 21
0

Here's a working solution:

  1. setRoom is asynchronous so your 2 console.log(theRoom) can't show the right value while you're still in the function.
  2. to handle the select change value, you can use the onChange React prop that allows you to catch every value change of a hook
  3. I put you 2 console.login a useEffect to allow you to see the changes of the theRoom and selectValue values
import React, { useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const [theRoom, setRoom] = useState(null);
  const [selectValue, setSelectValue] = useState(null);

  const createRoom = () => {
    setRoom({
      localparticipants: {}
    });
  };

  // everytime selectValue or theRoom values changed, this trigger this
  useEffect(() => {
    console.log(selectValue);
    console.log(theRoom);
  }, [selectValue, theRoom]);

  return (
    <div className="App">
      <select
        id="video-devices"
        onChange={(e) => setSelectValue(e.target.value)}
        value={selectValue}
      >
        <option value="1">1</option>
        <option value="2">2</option>
      </select>
      <button onClick={createRoom}>change obj</button>
    </div>
  );
}

VersifiXion
  • 2,152
  • 5
  • 22
  • 40