I am having a really bizarre bug. Occasionally, when I submit the form the "userId" cookie is not updated. I think I have isolated the problem to something to do with
return user.set({
    roomId: roomId,
    name: name
  }).then(() => alert("finished writing"))
as when the cookie isn't updated the "finished writing" alert is never called. I think it is something to with a promise not being resolved, and that taking up the thread so the .then is never run (and consequently the .then with the cookie update is never run). However, I don't really understand promises and I can't find what might be holding it up. If anyone could help me out or point out the bug it would be really appreciated. Here is the code:
function GamePage() {
  const {roomId} = useParams();
  const db = firebase.firestore();
  let history = useHistory();
  const [userIdExistsButWrongRoom, setUserIdExistsButWrongRoom] = useState(true);
  const userId = cookies.get('userId');
  useEffect(() => {
    if(!(typeof(userId)==="undefined")){
    db.collection("users").doc(userId).get().then(function(doc){
      if(doc.data().roomId === roomId){
          setUserIdExistsButWrongRoom(false);
        } 
      });
    }
  }, [db,roomId,userId]);
  if(cookies.get('roomId')===roomId){
    if(typeof(userId)==="undefined"){
      return (
        <div>
        <EnterName />
      </div>
      );
    } else {
        if(userIdExistsButWrongRoom){
          return (
            <div>
            <EnterName />
          </div>
          );
        } else {
          return (
            <div>
            <Game />
            </div>);
        }
      }
  } else {
    history.push("/");
    return (<div />);
  }
}
function EnterName() {
  const {roomId} = useParams();
  const [name, setName] = useState("");
  
  function handleChange(event) {
    setName(event.target.value);
  }
  function handleSubmit(event) {
    addNewUser(roomId,name).then(function(userId) {cookies.set('userId',userId)});
  }
  return (<form onSubmit={handleSubmit}>
    <label>
      Name:
      <textarea value={name} onChange={handleChange} />
    </label>
    <input type="submit" value="Submit" />
  </form>);
}
function Game() {
  const {roomId} = useParams();
  return (<div>
    <h1>
    {roomId}
    </h1>
  </div>);
}
//Add a new user with server generated unique ID, and the given room ID to the database
//Returns the doc
function addNewUser(roomId,name) {
  const db = firebase.firestore();
  const user = db.collection("users").doc()
  const userId = user.id;
  alert(userId);
  return user.set({
    roomId: roomId,
    name: name
  }).then(() => alert("finished writing"));
  
}
Edit
After Oliver's answer, I tried implementing an asynchoronus submitHandler. However, this caused the addNewUser function to not even be called. I found this question javascript async await Submitting a form with onsubmit using Promise which suggests that the problem with an asynchronus submitHandler is that it always returns a promise so it submits before the Promise resolves. I tried implementing their proposed fix (below) but now it is back to the orginal problem but just all the time now!
function EnterName() {
  const {roomId} = useParams();
  const [name, setName] = useState("");
  
  function handleChange(event) {
    setName(event.target.value);
  }
  async function handleSubmit(event) {
    let userId = await addNewUser(roomId, name);
    alert("test");
    cookies.set('userId',userId);
  }
  function submit(event){
    handleSubmit(event);
    return false;
  }
  return (<form onSubmit={submit}>
    <label>
      Name:
      <textarea value={name} onChange={handleChange} />
    </label>
    <input type="submit" value="Submit" />
  </form>);
}
function Game() {
  const {roomId} = useParams();
  return (<div>
    <h1>
    {roomId}
    </h1>
  </div>);
}
//Add a new user with server generated unique ID, and the given room ID to the database
//Returns the doc
async function addNewUser(roomId,name) {
  const db = firebase.firestore();
  const user = db.collection("users").doc()
  const userId = user.id;
  alert(userId);
  return user.set({
    roomId: roomId,
    name: name
  }).then(() => {
    alert("finished writing");
    return userId;
  });
}
 
    