根据子组件中父组件状态的更改,在父组件上执行代码

悉尼

我正在学习reactjs并制作测验应用程序。我想使用useEffect在父组件中执行一段代码。useEffect函数的依赖关系基于父组件的状态,该状态将在子组件中更改。我已将set方法发送给子组件。根据我的理解,useEffect函数应该在父组件中工作,但是没有发生。我究竟做错了什么?

我正在向子组件发送答案和setAnswers,并尝试在子组件中调用setAnswers时登录更新了答案的父组件。

父组件:

import React, { useState, useEffect, useRef } from 'react'
import axios from 'axios'
import { baseURL } from '../assets/axiosInstance'
import Row from 'react-bootstrap/Row'
import QuizCard from './QuizCard'
import Spinner from 'react-bootstrap/Spinner'
import Button from 'react-bootstrap/Button'

export default function QuizFetch(props) {

    const quiz_id = props.quiz_id
    const quiz_uri = props.quiz_uri
    const [quiz, setQuiz] = useState()
    const [answers, setAnswers] = useState([])
    const [correctAnswers, setCorrectAnswers] = useState([])
    const [my_error, setError] = useState({has_error: false, message: 0})
    const [apiCalling, setApiCalling] = useState(true)
    const [ansCounter, setAnsCounter] = useState(0)

    useEffect(()=>{
        console.log('answers changed')
    },[answers])


    const first_data_effect = useRef(true)
    useEffect(() => {
        if(first_data_effect.current){
            first_data_effect.current = false
            return
        }
            let ans = []
            let q_len = quiz.questions.length
            for(let c = 0; c < q_len; c++){
                let questions = quiz.questions[c]
                let a_len = questions.options.length;
                for (let d = 0; d < a_len; d++){
                    if (questions.options[d].correct_answer === 'yes'){
                        
                        ans[`question_${questions.id}`] = questions.options[d].id
                        
                    }
                }
            }
            console.log('ans',ans)
            setCorrectAnswers(ans)
            console.log('corr ans',correctAnswers)
            setAnsCounter(quiz.questions.length)
            console.log('qlen',quiz.questions.length)

    }, [quiz])

    useEffect(() => {
        axios.post(baseURL + 'quiz/get-quiz', {
            quiz_id: quiz_id,
            quiz_uri: quiz_uri
        }, {
            headers: {
                'Accept': 'application/json',
                'Authorization': `Bearer ${localStorage.getItem('scs_token')}`
            },
        })
            .then((response) => {
                const resp = response.data
                setQuiz(resp[0])
            })
            .catch((error) => {
                console.log("inside error")
                setError({
                    has_error: true,
                    message: error.response.data['message']
                })
            })
            .then(() => {
                setApiCalling(false)
            })
    }, [])


    if (apiCalling) {
        console.log('api calling true')
        return (
            <>
                <div style={{ height: "200px", display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                    <Spinner animation="grow" variant="primary" />
                </div>
            </>
        )
    } else if (my_error['has_error']) {
        console.log('error')
        return (
            <>
                <h1>Quiz: {props.quiz_uri}</h1>
                {my_error['message']}
            </>
        )
    } else {
        return (
            <>
            <div>
                <h1 style={{ textAlign: 'center'}}>
                    {quiz.quiz_title}
                </h1>
                Yet to Answer: {ansCounter}
                Answered: {answers.length}
                <Row style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                    {quiz.questions.map(q => (
                        <QuizCard key={q.id} quizid={quiz.id} question={q} answers={answers} setAnswers={setAnswers}/>
                    ))}
                </Row>
                <br />
                </div>
                <br /><br />

            </>
        )
    }

}

子组件:

import React, {useState, useEffect} from 'react'
import Col from 'react-bootstrap/Col'
import axios from 'axios'
import { baseURL } from '../assets/axiosInstance'
import Spinner from 'react-bootstrap/Spinner'


export default function QuizCard(props){
    const [question, setQuestion] = useState(props.question)
    const [showCorrect, setShowCorrect] = useState(false)
    // const [apiCalling, setApiCalling] = useState(false)

    const onChangeValue = (e) =>{
        setShowCorrect(true)
        let result = props.answers
        result[e.target.name] = e.target.value
        props.setAnswers(result)
        console.log('on change answers',props.answers)
        // setApiCalling(true)
        axios.post(baseURL + 'quiz/record-each-answer', {
            quiz_id: props.quizid,
            question_id: e.target.name,
            option_id: e.target.value
        }, {
            headers: {
                'Accept': 'application/json',
                'Authorization': `Bearer ${localStorage.getItem('scs_token')}`
            },
        })
            .then((response) => {
                console.log('successful')
            })
            .catch((error) => {
                console.log('failed')
            })

        
    }

    return(
        <>
        <Col md={3} xs={8} style={{margin:"5px",padding:"15px 10px", backgroundColor:"#343a40", borderRadius:'15px', color:"white", position:"relative",top:'0px'}}>
        <h5 style={{marginLeft:"10px"}}>{question.question}</h5> 
        {/* {apiCalling ? <Spinner animation="border" variant="primary" size="sm" /> : ""} */}
        <div style={{marginLeft:"10px"}}>
            {question.options.map(option=>(
                <div key={option.id}>
                    <input 
                    type="radio" 
                    disabled={showCorrect}
                    {...props.answers[`question_${question.id}`] === option.id ? "checked" : ""} 
                    value={option.id} 
                    onClick={(e)=>onChangeValue(e)} 
                    name={`question_${question.id}`}/>
                &nbsp;<span style={{width:'100%', backgroundColor:((showCorrect && option.correct_answer) === "yes" ? "green": "")}} >{option.answer}</span></div>
                
            ))}
      </div>
      
        </Col>
        
        </>
    )
}
特里克森

问题在于您正在更改状态,而不是创建包含新状态的新对象。您永远都不应改变状态。React通过身份比较状态,因为您只是向同一对象添加属性,所以React认为状态没有改变,因为它仍然是同一对象。您需要创建一个新对象,并将旧状态与新答案合并:

const onChangeValue = (e) => {
    // ...
    props.setAnswers(currentAnswers => ({...currentAnswers, [e.target.name]: e.target.value}));
    // ...
}
   

请注意,这是如何使用的回调版本的setAnswers它接受一个以当前状态为参数的函数,并应返回新状态。当您要基于当前状态更新状态时,应始终使用该名称。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

子组件更新时更改父状态

来自分类Dev

当父状态在React中更改时停止渲染子组件

来自分类Dev

从React中的子组件更改父状态(无Redux)

来自分类Dev

如何从功能组件的父级更改子状态组件

来自分类Dev

从子组件更改父组件中的状态,然后将该状态作为属性传递,并在子组件中更改状态

来自分类Dev

处理子组件中的父状态

来自分类Dev

更改 reactJs 父组件中的状态不会更改 react 子组件中的道具

来自分类Dev

如何从子组件更改父组件的状态?

来自分类Dev

如何从子组件更改父组件的状态?

来自分类Dev

ReactJS - 根据嵌套路由更改父组件中的组件

来自分类Dev

反应 子组件正在更改父组件

来自分类Dev

单击带有React JS中特定键的子组件时更改父组件的状态

来自分类Dev

如何设置子组件的子组件的父组件状态

来自分类Dev

如何从类组件(父组件)更改功能组件(子组件)中的useState

来自分类Dev

根据子组件的数据计算父状态:ReactJS

来自分类Dev

在Angular的父组件中创建子组件

来自分类Dev

在子组件的状态之间共享父状态?

来自分类Dev

如果父状态值更改,如何更新子组件

来自分类Dev

React:子组件未在父状态更改时呈现

来自分类Dev

响应子组件在父状态更改后不更新

来自分类Dev

父状态更改时子组件不会更新

来自分类Dev

子组件未因父状态更改而更新

来自分类Dev

在React中,父组件如何通过响应在子组件中执行异步获取功能来设置状态?

来自分类Dev

父状态更新时更新子组件

来自分类Dev

父状态更新时更新子组件

来自分类Dev

父状态不更新子组件

来自分类Dev

父状态更改后,组件不会更新

来自分类Dev

React:单击组件以更改父状态

来自分类Dev

如何在父级的子级组件中设置状态?

Related 相关文章

  1. 1

    子组件更新时更改父状态

  2. 2

    当父状态在React中更改时停止渲染子组件

  3. 3

    从React中的子组件更改父状态(无Redux)

  4. 4

    如何从功能组件的父级更改子状态组件

  5. 5

    从子组件更改父组件中的状态,然后将该状态作为属性传递,并在子组件中更改状态

  6. 6

    处理子组件中的父状态

  7. 7

    更改 reactJs 父组件中的状态不会更改 react 子组件中的道具

  8. 8

    如何从子组件更改父组件的状态?

  9. 9

    如何从子组件更改父组件的状态?

  10. 10

    ReactJS - 根据嵌套路由更改父组件中的组件

  11. 11

    反应 子组件正在更改父组件

  12. 12

    单击带有React JS中特定键的子组件时更改父组件的状态

  13. 13

    如何设置子组件的子组件的父组件状态

  14. 14

    如何从类组件(父组件)更改功能组件(子组件)中的useState

  15. 15

    根据子组件的数据计算父状态:ReactJS

  16. 16

    在Angular的父组件中创建子组件

  17. 17

    在子组件的状态之间共享父状态?

  18. 18

    如果父状态值更改,如何更新子组件

  19. 19

    React:子组件未在父状态更改时呈现

  20. 20

    响应子组件在父状态更改后不更新

  21. 21

    父状态更改时子组件不会更新

  22. 22

    子组件未因父状态更改而更新

  23. 23

    在React中,父组件如何通过响应在子组件中执行异步获取功能来设置状态?

  24. 24

    父状态更新时更新子组件

  25. 25

    父状态更新时更新子组件

  26. 26

    父状态不更新子组件

  27. 27

    父状态更改后,组件不会更新

  28. 28

    React:单击组件以更改父状态

  29. 29

    如何在父级的子级组件中设置状态?

热门标签

归档