I have an issue with my project.
I need to pass the state of a countdown Child component to a Parent component, to make the Parent component visible or not if the time is 0.
this is my countdown component
import { Typography, Paper, Grid } from '@mui/material';
import React, { useEffect, useRef, useState } from 'react';
const formatTime = (time) => {
let minutes = Math.floor(time / 60);
let seconds = Math.floor(time - minutes * 60);
if (minutes <= 10) {
minutes = '0' + minutes;
}
if (seconds <= 10) {
seconds = '0' + seconds;
}
return minutes + ':' + seconds;
};
function CountDown(props) {
const [countdown, setCountdown] = useState(props.seconds);
const [onTime, setOnTime] = useState(true);
const timertId = useRef();
useEffect(() => {
timertId.current = setInterval(() => {
setCountdown((prev) => prev - 1);
}, 1000);
return () => clearInterval(timertId.current);
}, []);
useEffect(() => {
if (countdown <= 0) {
clearInterval(timertId.current);
setOnTime(false);
}
}, [countdown]);
return (
<Grid container>
<Grid item xs={5}>
<Paper elevation={0} variant='outlined' square>
<Typography component='h6' fontFamily={'Roboto'}>
Timer:
</Typography>
</Paper>
</Grid>
<Grid item xs={5}>
<Paper
elevation={0}
variant='outlined'
square
sx={{ bgcolor: 'lightblue' }}
>
<Typography component='h6' fontFamily={'Roboto'}>
{formatTime(countdown)}
</Typography>
</Paper>
</Grid>
</Grid>
);
}
export default CountDown;
I want to pass the OnTime state to the Parent component:
export default function QuestionCard() {
const [questions, setQuestions] = useState([]);
const [clickedIndex, setClickedIndex] = useState(0);
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
const [value, setValue] = useState(null);
const { isLoading, error, sendRequest: getQuestions } = useAxios();
const { sendRequest: getAnswers } = useAxios();
const handleSubmit = () => {
setValue(true);
};
const handleSelectedItem = (index) => {
setClickedIndex(index);
};
const handleChange = (e) => {
setValue(e.target.value);
};
useEffect(() => {
const transformQuestions = (questionObj) => {
const loadedQuestions = [];
for (const questionKey in questionObj) {
loadedQuestions.push({
id: questionKey,
id_test: questionObj[questionKey].id_test,
tipologia_domanda: questionObj[questionKey].tipologia_domanda,
testo: questionObj[questionKey].testo,
immagine: questionObj[questionKey].immagine,
eliminata: questionObj[questionKey].eliminata,
});
}
setQuestions(loadedQuestions);
};
getQuestions(
{
method: 'GET',
url: baseURL_Q,
},
transformQuestions
);
}, [getQuestions]);
let questionsTitle = questions.map((element) => `${element.testo}`);
let questionId = questions.map((element) => `${element.id}`);
return (
<Grid container spacing={1}>
<Grid item xs={10}>
<Box
sx={{
minWidth: 275,
display: 'flex',
alignItems: 'center',
paddingLeft: '50%',
paddingBottom: '5%',
position: 'center',
}}
>
<Card
variant='outlined'
sx={{
minWidth: 400,
}}
>
<CardContent>
<Grid container spacing={0}>
<Grid item xs={8}>
<Typography
variant='h5'
component='div'
fontFamily={'Roboto'}
>
Nome Test
</Typography>
</Grid>
<Grid item xs={4}>
<CountDown seconds={300} />
</Grid>
</Grid>
<LinearProgress variant='determinate' value={1} />
<Typography
sx={{ mb: 1.5, mt: 1.5 }}
fontFamily={'Roboto'}
fontWeight={'bold'}
>
{questionsTitle[currentQuestionIndex]}
</Typography>
<ButtonGroup
fullWidth
orientation='vertical'
onClick={handleSubmit}
onChange={handleChange}
>
<ListItemButton
selected={clickedIndex === 1}
onClick={() => handleSelectedItem(1)}
>
Risposta 1
</ListItemButton>
<ListItemButton
selected={clickedIndex === 2}
onClick={() => handleSelectedItem(2)}
>
Risposta 2
</ListItemButton>
<ListItemButton
selected={clickedIndex === 3}
onClick={() => handleSelectedItem(3)}
>
Risposta 3
</ListItemButton>
<ListItemButton
selected={clickedIndex === 4}
onClick={() => handleSelectedItem(4)}
>
Risposta 4
</ListItemButton>
</ButtonGroup>
</CardContent>
<CardActions>
<Button onClick={goToNext} disabled={!value} variant='contained' size='small'>
Avanti
</Button>
</CardActions>
</Card>
</Box>
</Grid>
</Grid>
);
}
The idea is that onTime is true, the QuestionCard gets rendered with question and answers, if onTime is false, it gets rendered an alert or a text. How can I pass the onTime state from Countdown to QuestionCard? Thank you
3
Answers
Move your
onTime
hook to the parent object (QuestionCard
), and pass the setter functionsetOntime
to the child.Since you aren’t using
onTime
inCountDown
, it doesn’t make sense to define it there. Using the method described above will move your state object to where it needs to be, an allow greater control by passing the setter function to where it is required.I think the best practice here is to manage the
onTime
state in the parent, and pass thesetOnTime
function from the Parent to theCountDown
component through the props, so it will be able to change the onTime state in the parent.Suggestion for implementation:
Just create a new state in your parent component and pass its setter function to the child component and now you can update a parent’s state in the child component. Please check below code
Your child component
Your parent component
Happy Coding 😉