Search code examples
javascriptreactjsinputreset

How to reset input value after a button click that is not inside of a form in React.js


I'm currently learning React.js and I'm trying to make a little trivia game. The code overall needs more polishing but what I'm trying to achieve for the moment is that I want my input field to reset its value after the button is clicked. I tried clearing the text using e.target.reset() inside the onChange function that sets the input value inside the state, but that was a bit foolish since it throws errors left and right after starting typing. I also tried doing some tricks with a separate function which sets the ans to an empty string and then use it as a defaultValue/value but that wouldn't work either.

I would like not to use forms for this, since every similar question was related to forms. Any sort of help or tip is greatly appreciated.

import React, { useState, useEffect } from 'react'
import './Quiz.css';
import { Button } from '@material-ui/core';

function Quiz(props) {

    const [question, setQuestion] = useState('')
    const [category, setCategory] = useState('')
    const [correctAns, setCorrectAns] = useState('')
    const [ans, setAns] = useState('')
    const [options, setOptions] = useState([])



    let url = 'https://opentdb.com/api.php?amount=1&type=multiple'
    useEffect(() => {
        try {
            async function fetcher() {
                const quiz = await fetch(url)
                const res = await quiz.json();
                setCategory(res.results[0].category.replace(":", " ->"));
                setQuestion(res.results[0].question.replace(/"/g, "''").replace(/'/g, "'"));
                setCorrectAns(res.results[0].correct_answer);
                props.setCounter(props.counter)

                const incorrect = res.results[0].incorrect_answers
                const correct = res.results[0].correct_answer
                const concat = incorrect.concat(correct)

                const shuffle = (a) => {
                    for (let i = a.length - 1; i > 0; i--) {
                        const j = Math.floor(Math.random() * (i + 1));
                        [a[i], a[j]] = [a[j], a[i]];
                    }
                    setOptions(a)
                    return a;
                }
                shuffle(concat);
            }
            fetcher(url);
        }
        catch (e) {
            console.log(e)
        }
    }, [url, props])


    const input = (e) => {
        setAns(e.target.value)
    }

    const verify = () => {
        let randomizer = Math.floor(Math.random() * 49)
        if (ans === correctAns) {
            props.setCounter(props.counter + 1)
            url = `https://opentdb.com/api.php?amount=${randomizer}&type=multiple`
        } else {
            props.setCounter(props.counter * 0);
            alert('You lost! All your points are now gone')
            window.location.reload(false)
        }

    }

    return (
        <div className="card">
            Category -> {category}<br /><br />
            Question -> {question} <br /><br />
            <ul>
                <li>I. {options[0]}</li>
                <li>II. {options[1]}</li>
                <li>III. {options[2]}</li>
                <li>IV. {options[3]}</li>
            </ul>
            Your answer: <input type="text" onChange={input} /> <br /> <br />
            <Button variant="contained" color="secondary" onClick={verify} className="btn">
                Answer!
            </Button>

        </div >
    )
}

export default Quiz

Solution

  • Thanks to the help of others on this beautiful platform, I found an answer to it for anyone else who might encounter this in the future. So, what I did was the following:

    1. I added a new piece of state: const [value, setValue] = useState('').

    2. I used it inside the input function like this:

    const input = (e) => {
            setAns(e.target.value)
        >>> setValue(e.target.value)
        }
    
    1. Added setValue('') to the very end of the verify function, outside the if statement.

    2. Added value={value} to <input>'s attributes.