• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Input 'radio' w React

Object Storage Arubacloud
+1 głos
119 wizyt
pytanie zadane 20 lipca 2021 w JavaScript przez agapoli Początkujący (330 p.)

Hej, piszę quiz w React, gdzie prawidłową odpowiedź można zaznaczyć poprzez input type "radio". Problem w tym, że dopiero za drugim kliknięciem na ekranie widać rzeczywiście zaznaczoną odpowiedź. Stan natomiast zmienia się prawidłowo, za pierwszym kliknięciem. Czy ktoś ma pomysł o co może chodzić? W konsoli nie wyświetla się żaden błąd.

Dodatkowo, chciałabym żeby po kliknięciu "Sprawdź" i wyświetleniu prawidłowej odpowiedzi wszystkie inputy miały atrybut 'disabled', ale kiedy to robię input zostaje odznaczony.

Cały kod jest dość spory, dlatego niżej wrzucam fragmenty gdzie według mnie może być błąd. Podaję też link do repo z całym kodem: https://github.com/agapoli89/WroGuide-update

Z góry bardzo dziękuję za wszelką pomoc.

import { useState } from 'react';

import QuizStart from './QuizStart';
import QuizQuestion from './QuizQuestion';
import QuizSummary from './QuizSummary';
import { quizData } from './QuizData';

import './Quiz.scss';

const Quiz = () => {
    const [slideNumber, setSlideNumber] = useState(0);
    const [selectedAnswer, setSelectedAnswer] = useState('');
    const [answerIsNotSelected, setAnswerIsNotSelected] = useState(false);
    const [isAnswerVisible, setIsAnswerVisible] = useState(false);
    const [score, setScore] = useState(0);
    const [inputChecked, setInputChecked] = useState(false);

    const handleChangeInputChecked = () => setInputChecked(true);

    const handleChangeSlide = () => {
        if (slideNumber === 6) {
            setSlideNumber(0);
            setScore(0);
            return;
        }
        if (isAnswerVisible || slideNumber === 0) {
            setSelectedAnswer('');
            setSlideNumber(prev => prev + 1);
            setIsAnswerVisible(false);
            setAnswerIsNotSelected(false);
            return;
        } 
        if (!isAnswerVisible) setInputChecked(false);
        checkCorrectAnswer();
    }

    const handleOnChangeAnswer = e => {
        setSelectedAnswer(e.target.value);
    }

    const checkCorrectAnswer = () => {

        const currentQuestion = quizData.filter(question => question.id === Number(slideNumber))[0];
        const correctAnswer = currentQuestion.answers.filter(answer => answer.correct === true)[0].id;

        if (correctAnswer === selectedAnswer) {
            setScore(prev => prev + 1);
        }
        setIsAnswerVisible(true);
        setAnswerIsNotSelected(false);
    }

    const handleNoAnswerSelected = () => {
        setAnswerIsNotSelected(true); 
    }

    const quizContent = slideNumber === 0 
    ? <QuizStart click={handleChangeSlide}/> 
    : slideNumber === 6
        ? <QuizSummary score={score} click={handleChangeSlide}/>
        : <QuizQuestion 
            number={slideNumber} 
            isAnswerVisible={isAnswerVisible} 
            answerIsNotSelected={answerIsNotSelected} 
            selectedAnswer={selectedAnswer}
            inputChecked={inputChecked}
            clickChangeSlide={handleChangeSlide} 
            clickCheckAnswer={checkCorrectAnswer} 
            clickNoAnswerSelected={handleNoAnswerSelected}
            changeAnswer={handleOnChangeAnswer}
            handleChangeInputChecked={handleChangeInputChecked}
          />;

    return (  
        <section id="quiz" className="section quiz">
            {quizContent} 
        </section>
    );
}
 
export default Quiz;

 

import { quizData } from './QuizData';
import Button from '../../Button/Button';

const QuizQuestion = ({ 
        number, 
        isAnswerVisible, 
        answerIsNotSelected, 
        clickChangeSlide, 
        clickCheckAnswer, 
        clickNoAnswerSelected, 
        selectedAnswer, 
        changeAnswer, 
        inputChecked, 
        handleChangeInputChecked 
    }) => {
    
    const currentQuestion = quizData.filter(({id}) => id === number);
    const checkedAnswer = currentQuestion[0].answers.filter(answer => answer.id === selectedAnswer)[0];

    const currentAnswers = currentQuestion[0].answers.map(({id, text}) => (
        <label key={id}>
            <input 
                type="radio" 
                value={id} 
                name={number}  
                disabled={isAnswerVisible ? true : false} 
                checked={inputChecked} 
                onChange={handleChangeInputChecked}
                onClick={changeAnswer}
            /> {text}
        </label>
    ))
    
    const answerToDisplay = isAnswerVisible
        ? (
            <>
                <p className={`alert ${checkedAnswer.correct ? "alert-success" : "alert-danger"} mt-4`}>{checkedAnswer.comment}</p>
                <p>{currentQuestion[0].correctAnswer}</p>
            </>
        ) 
        : answerIsNotSelected
            ? (<p className='alert alert-danger mt-4'>Zaznacz jedną z odpowiedzi</p>)
            : null

    const buttonText = !isAnswerVisible 
        ? "Sprawdź"
        : number === 5
            ? "Sprawdź wynik"
            : "Następne pytanie"

    const clickFunction = buttonText === "Sprawdź" & selectedAnswer
        ? clickCheckAnswer
        : selectedAnswer
            ? clickChangeSlide
            : clickNoAnswerSelected

    return (  
        <>
            <h4>{`${number}. ${currentQuestion[0].question}`}</h4>
            {currentAnswers}
            {answerToDisplay}
            <Button text={buttonText} click={clickFunction} />
        </>
    );
}
 
export default QuizQuestion;
import './Button.scss';

const Button = ({
    text, 
    additionalClass,
    type="button",
    click
    }) => {
    return (  
        <button 
            type={type}
            className={`btn button button--center px-4 mt-4 ${additionalClass}`}
            onClick={click}
        >
            {text}
        </button>
    );
}
 
export default Button;
export const quizData = [
    {
        id: 1,
        question: 'Jak myślisz, dlaczego jednym z kolorów użytych na mojej stronie internetowej jest pomarańczowy?',
        answers: [
            {
                id: 'a',
                text: 'Kolor pomarańczowy widnieje na fladze Wrocławia?',
                correct: false,
                comment: 'Niestety nie. Na fladze Wrocławia widnieją kolory: czerwony i żółty. Nie mogę przyznać punktu mimo, że te dwie barwy po połączeniu faktycznie tworzą pomarańczowy :)',
            },
            {
                id: 'b',
                text: "Uwielbiam pomarańcze?",
                correct: false,
                comment: 'Niestety nie. Lubię pomarańcze, ale to nie jest powód dla którego pomarańczowy znalazł się na mojej stronie.',
            },
            {
                id: 'c',
                text: 'Jest to nawiązanie do Pomarańczowej Alternatywy?',
                correct: true,
                comment: 'Tak!'
            }
        ],
        correctAnswer: 'Poprawna odpowiedź: Pomarańczowa Alternatywa, czyli ruch opozycyjno-artystyczny, który narodził się we Wrocławiu w latach 80. XX wieku. Jego celem była walka z ówczesnym systemem za pomocą śmiechu i absurdu. Już w trakcie stanu wojennego na ulicach Wrocławia, w miejsce zatartych przez władze haseł antykomunistycznych, zaczęły pojawiać się rysunki krasnoludków. Później grupa skupiła się na organizacji happeningów (m.in. Krasnoludki na Świdnickiej). Od lat 90., Pomarańczowa Alternatywa znacznie ograniczyła swoją działalność, ale krasnoludki pozostały i teraz postrzegane są jako jeden z symboli Wrocławia.',
    },
    {
        id: 2,
        question: 'Jak nazywa się krasnal, widniejący na pierwszym zdjęciu tej witryny?',
        answers: [
            {
                id: 'a',
                text: 'Turysta?',
                correct: true,
                comment: 'Dobrze!',
            },
            {
                id: 'b',
                text: "WrocLovek?", 
                correct: false,
                comment: 'Niestety nie. Przyjrzyj się dokładnie co krasnal trzyma w ręce i na szyi..',
            },
            {
                id: 'c',
                text: 'Życzliwek?',
                correct: false,
                comment: 'Niestety nie. Przyjrzyj się dokładnie co krasnal trzyma w ręce i na szyi..'
            }
        ],
        correctAnswer: 'Poprawna odpowiedź to: Turysta. Na szyi ma zawieszony aparat, a w ręku trzyma najprawdopodomniej mapę. Możecie go spotkać przed Centrum Informacji Turystycznej na Rynku. Każdy krasnal ma swoje atrybuty, dzięki którym łatwiej go rozpoznać. Często też ich lokalizacja jest nieprzypadkowa, np. Bankuś stoi przed jednym z banków, a Śpiewak Operowy przed... budynkiem Opery :)',
    },
    {
        id: 3,
        question: 'Kolejnym kolorem, którego sporo na mojej stronie jest niebieski. Woda mocno wpływa na krajobraz Wrocławia, który bywa nazywany:',
        answers: [
            {
                id: 'a',
                text: "Wenecją Północy?",
                correct: true,
                comment: 'Prawidłowa odpowiedź! :)',
            },
            {
                id: 'b',
                text: "Polskim Amsterdamem?",
                correct: false,
                comment: 'Mogłoby tak być, chociaż ja nigdy nie spotkałam się z tym określeniem odnoście Wrocławia. Ponoć Polskim Amsterdamem nazywana jest Bydgoszcz.',
            },
            {
                id: 'c',
                text: 'Perłą znad Odry?',
                correct: false,
                comment: 'Coś w tym jest, ale póki co nazwa ta jeszcze się nie przyjęła :)'
            }
        ],
        correctAnswer: 'Poprawna odpowiedź: Wenecja Północy. Wrocław często bywa porównywany do Wenecji między innymi ze względu na liczbę mostów i kładek. O Wrocławiu mówi się też: "miasto stu mostów", choć w rzeczywistości posiada ich więcej.',
    },
    {
        id: 4,
        question: 'Ile katedr jest we Wrocławiu?',
        answers: [
            {
                id: 'a',
                text: "Jedna. Katedra św. Jana Chrzciciela na Ostrowie Tumskim?",
                correct: false,
                comment: 'Niestety nie. Katedra rzymskokatolicka pw. św. Jana Chrzciciela jest najbardziej znana, ale nie jedyna we Wrocławiu.',
            },
            {
                id: 'b',
                text: "Pięć",
                correct: true,
                comment: 'Zgadza się.',
            },
            {
                id: 'c',
                text: 'Siedem?',
                correct: false,
                comment: 'Niestety nie. We Wrocławiu jest sporo katedr, ale nie aż 7.'
            }
        ],
        correctAnswer: 'Poprawna odpowiedź: Pięć. Wrocławskie katedry (rozumiane jako kościoły biskupie) to: wspomniana już katedra św. Jana Chrzciciela, katedra polskokatolicka św. Marii Magdaleny, katedra greckokatolicka św. Wincentego i św. Jakuba, katedra prawosławna Narodzenia Przenajświętszej Bogurodzicy oraz kościół Opatrzności Bożej.',
    },
    {
        id: 5,
        question: 'W 1842 roku z Wrocławia odjechał pierwszy pociąg na obecnych ziemiach polskich. Czy wiesz jakie miasto było celem jego podróży?',
        answers: [
            {
                id: 'a',
                text: "Oleśnica?",
                correct: false,
                comment: 'Niestety nie. Chociaż linia kolejowa: Wrocław Mikołajów - Oleśnica także ma długą historię, bo pierwszy pociąg na tej trasie wyruszył już w 1868 roku.',
            },
            {
                id: 'b',
                text: "Oława.",
                correct: true,
                comment: 'Dokładnie tak!',
            },
            {
                id: 'c',
                text: 'Jelenia Góra?',
                correct: false,
                comment: 'Niestety nie. Pociągiem z Wrocławia do Jeleniej Góry i na odwrót dojechać można było przez Wałbrzych Główny od 1868 roku.'
            }
        ],
        correctAnswer: 'Poprawna odpowiedź: Oława. 22 maja 1842 roku o godzinie 6:00 rano z Dworca Górnośląskiego we Wrocławiu odjechał pierwszy oficjalny pociąg do Oławy (trasa liczyła ok. 27 kilometrów, a przejazd trwał 42 minuty). Przypomnijmy, że zarówno Wrocław jak i Oława znajdowały się wtedy na ziemiach niemieckich.',
    },
]

 

komentarz 20 lipca 2021 przez ScriptyChris Mędrzec (190,190 p.)
<input 
  type="radio"
  value={id} 
  name={number}  
  disabled={isAnswerVisible ? true : false} 
  checked={inputChecked} 

  onChange={handleChangeInputChecked}
  onClick={changeAnswer}
/>

Dlaczego na tym radio inpucie jednocześnie zmieniasz stan na onClick i onChange? Tutaj raczej powinien być tylko onChange.

komentarz 21 lipca 2021 przez agapoli Początkujący (330 p.)
Faktycznie, niepotrzebnie zamotałam. Dzięki, już zmieniłam, ale to wciąż nie rozwiązuje problemu..

1 odpowiedź

+1 głos
odpowiedź 21 lipca 2021 przez pablop76 VIP (123,180 p.)
edycja 21 lipca 2021 przez pablop76
 const [inputChecked, setInputChecked] = useState(false);  

checked={inputChecked} 

Ta właściwość jest moim zdaniem niepotrzebna. Jeżeli chcesz sprawdzić, który checkbox jest checked to pobierz info z e.target

Wartość checked - wartość logiczna wskazująca, czy ten przycisk opcji jest domyślnie zaznaczoną pozycją w grupie, więc nie ustawiasz go klikając w radio.

komentarz 21 lipca 2021 przez agapoli Początkujący (330 p.)
Tego stanu użyłam, ponieważ inaczej przy przejściu do następnego pytania zaznaczony jest input, który był odpowiedzią na poprzednie pytanie, więc chciałam w ten sposób go odznaczyć. Ale faktycznie chyba coś przekombinowałam. Spojrzę na to jeszcze raz na spokojnie. Dzięki

Podobne pytania

+1 głos
2 odpowiedzi 194 wizyt
pytanie zadane 17 kwietnia 2021 w HTML i CSS przez Rafał Termoaktywny Początkujący (400 p.)
+1 głos
1 odpowiedź 184 wizyt
pytanie zadane 26 stycznia 2021 w HTML i CSS przez JBacob Nowicjusz (130 p.)
0 głosów
0 odpowiedzi 131 wizyt
pytanie zadane 15 października 2019 w PHP przez jared Gaduła (3,600 p.)

92,592 zapytań

141,441 odpowiedzi

319,701 komentarzy

61,975 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...