David Klimaszewski
David Klimaszewski

Reputation: 1

Incorrect state when onClick fired

I'm using AlephJS for the first time, and I think I'm running into a closure issue with my code, but for the life of me I can't figure it out. As you can see I have a modal and a page, onClick I'm dispatching a function, but it's using the inital state, instead of the values updated in the modal. I could probably use useRef(), but, I shouldn't have to? Any info or pointers in the right direction would be much appreciated. Code:

import React, {
  useEffect,
  useState
} from 'react';
import "./main.css";
import { useGames } from "~/lib/gamesContext.tsx";
// import M from "materialize-css";

export default () => {
  const { dispatch } = useGames();
  const [modalOpen, setModalOpen] = useState(false);
  const [newGame, setNewGame] = useState({
    players: [],
    type: ""
  });

  const handleContentLoaded = () => {
    const selects = document.querySelectorAll('select');
    //@ts-ignore
    M.FormSelect.init(selects, {});
    const chips = document.querySelectorAll('.chips');
    //@ts-ignore
    M.Chips.init(chips, {
      placeholder: 'Enter a Player',
      secondaryPlaceholder: '+Player',
      onChipAdd: (element: Element, chip: Element) => updatePlayers(element, chip),
      onChipDelete: (element: Element, chip: Element) => updatePlayers(element, chip)
    });
  };

  const updatePlayers = (element: Element, chip: Element) => {
    //@ts-ignore
    const chipData = element[0].M_Chips.chipsData.map(item => item.tag);
    setNewGame(newGame => ({
      ...newGame,
      players: chipData
    }));
  }

  const resetState = () => setNewGame({
    players: [],
    type: ""
  });

  useEffect(() => {
    handleContentLoaded();
  }, []);

  console.log("New Game", newGame);

  return (
    <>
      <div className={modalOpen ? "custom-modal" : "custom-modal closed"}>
        <div className="card modal-start-container">
          <div className="card-content">
            <span className="card-title">New Game</span>
            <div className="input-field col s12">
              <select value={newGame.type} onChange={(event) => {
                setNewGame(newGame => ({
                  ...newGame,
                  type: event.target.value
                }))
              }}>
                <option value="" disabled>Choose a game</option>
                <option value="rummy">Rummy</option>
                <option value="upAndDown">Up and Down</option>
              </select>
              <label>Game Type</label>
            </div>
            <div className="chips chips-placeholder"></div>
          </div>
          <div className="card-action">
            <a 
              onClick={() => {
                console.log("on click: ", newGame);
                dispatch({
                  type: "addGame",
                  payload: {
                    ...newGame,
                    index: `${newGame.type}${Date.now()}`
                  }
                });
                setModalOpen(false);
                resetState();
              }}
              className="waves-effect waves-green btn-flat">Start</a>
          </div>
        </div>
      </div>
      <div className={`container ${modalOpen ? "blur" : ""}`}>
        <blockquote>
          <h4>"Weird how the scorekeeper always wins..."</h4>
          <p>- every sore loser everywhere</p>
        </blockquote>
        <div className="flex-col">
          <p className="flow-text">
            Today it's easier to find a tablet or phone, than pen and paper. So
            we've created an app that will let you keep score of all your
            favorite card games, from your favorite digital device.
          </p>
          <a className="waves-effect waves-light btn" onClick={() => setModalOpen(true)}>
            New Game
          </a>
        </div>
      </div>
    </>
  );
}

Link to code in the TypeScript playground

Upvotes: 0

Views: 64

Answers (0)

Related Questions