skip to Main Content

I’m trying to implement a functionality wherein after I click a button, a popup should open with some content, and once it is closed, the button should be permanently disabled.

Now, I’ve implemented the same functionality for another button which works fine in the same component using: –

    const fiftyClickHandler = (event) => {
        event.currentTarget.disabled = true;
        setIsFiftyActive(true);
    }

but it just doesn’t work for the other button (ask-the-expert)

import React from 'react'
import OpenAI from "openai";
import Popup from "./Popup";
export default function Helpline({ data, questionNumber, setIsFiftyActive }) {
    //* Open source API key
    const openai = new OpenAI({
        apiKey: process.env.REACT_APP_API_KEY,
        baseURL: process.env.REACT_APP_BASE_URL,
        dangerouslyAllowBrowser: true
    });
    const [PopupModalOpen, setPopupModalOpen] = React.useState(false)
    const [gptData, setGptData] = React.useState([]);
  
    const expertClickHandler = async (event) => {
        //* Constructing object that would have all answer options and questions to be sent to GPT
        let ansOptions = "";
        data[questionNumber - 1].answers.map((item) => {
            return ansOptions += item.text + ",";
        })
        let contentObj = {
            ansOptions,
            question: data[questionNumber - 1].question
        }
        try {
            const completion = await openai.chat.completions.create({
                model: "pai-001",
                messages: [
                    { role: "system", content: "You are an expert in trivia and general knowledge and are an assistant in a quiz show helping users when they are in need" },
                    {
                        role: "user",
                        content: contentObj,
                    },
                ],
            });
            setGptData(completion.choices[0].message.content);
            console.log(gptData);
        } catch (error) {
            setGptData("Null");
            console.log("Error fetching results")
        }
        setPopupModalOpen(true);
        event.currentTarget.disabled = true;
    }

    const fiftyClickHandler = (event) => {
        event.currentTarget.disabled = true;
        setIsFiftyActive(true);
    }
    return (
        PopupModalOpen ?
            <div>
                <Popup PopupModalOpen={PopupModalOpen} setPopupModalOpen={setPopupModalOpen} />
            </div> :
            //* Expert answer state === false meaning modal is not open */
            <div className="helpline">
                <button className="game-btn" id="fifty-fifty" onClick={fiftyClickHandler}>
                    Fifty Fifty
                </button>
                <button className="game-btn" id="ask-the-expert" onClick={expertClickHandler}>
                    Ask the expert
                </button>
            </div>

    )
}

Why is this happening?

There are two ways to solve this ->

  1. Refs: – I’ve tried using it, but it doesn’t work because after closing the modal, the ref’s value is set to null again and the button doesn’t; get disabled.

  2. State: – An obvious solution, but I want to use them when there is no other solution available.

2

Answers


  1. You should disable the button after close the popup rather than opening it. I will use useRef hook to create a buttonRef. I would use useStateCallback hook create the state for popup because I can use the setState(newState, () => { /** after state and component updated */})

    Here is an example:

    import React, { useCallback, useEffect, useRef, useState } from 'react';
    
    export function useStateCallback<T>(
      initialState: T
    ): [T, (state: T, cb?: (state: T) => void) => void] {
      const [state, setState] = useState(initialState);
      const cbRef = useRef<((state: T) => void) | undefined>(undefined);
    
      const setStateCallback = useCallback((state: T, cb?: (state: T) => void) => {
        cbRef.current = cb;
        setState(state);
      }, []);
    
      useEffect(() => {
        if (cbRef.current) {
          cbRef.current(state);
          cbRef.current = undefined;
        }
      }, [state]);
    
      return [state, setStateCallback];
    }
    
    function App() {
      const [PopupModalOpen, setPopupModalOpen] = useStateCallback(false);
      const buttonRef = React.useRef<HTMLButtonElement>(null);
    
      const expertClickHandler = () => {
        setPopupModalOpen(true);
      };
    
      return PopupModalOpen ? (
        <dialog
          open={PopupModalOpen}
          onClick={() =>
            setPopupModalOpen(false, () => {
              if (buttonRef.current) {
                buttonRef.current.disabled = true;
              }
            })
          }
        >
          content
        </dialog>
      ) : (
        <button ref={buttonRef} onClick={expertClickHandler}>
          Ask the expert
        </button>
      );
    }
    
    export default App;
    

    stackblitz

    Login or Signup to reply.
  2. To solve this problem, you can modify the expertClickHandler function to ensure the button is disabled permanently after the popup is closed.

    const expertClickHandler = async (event) => {
        try {
            // Construct object and send request to GPT API
            let ansOptions = "";
            data[questionNumber - 1].answers.map((item) => {
                return ansOptions += item.text + ",";
            });
            let contentObj = {
                ansOptions,
                question: data[questionNumber - 1].question
            };
            const completion = await openai.chat.completions.create({
                model: "pai-001",
                messages: [
                    { role: "system", content: "You are an expert in trivia and general knowledge and are an assistant in a quiz show helping users when they are in need" },
                    { role: "user", content: contentObj },
                ],
            });
            setGptData(completion.choices[0].message.content);
            console.log(gptData);
        } catch (error) {
            setGptData("Null");
            console.log("Error fetching results");
        }
        setPopupModalOpen(true);
        
        // Disable the button
        event.currentTarget.disabled = true;
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search