Home > Mobile >  React child class receiving undefined props even if class is mounted
React child class receiving undefined props even if class is mounted

Time:01-15

I'm trying to send an object as 'props' from a parent Class into a Child class with the intention of showing information:

Parent class

const TaskDetail = () => {

    //Get parameter from URL
    const { id } = useParams()

    const [taskDetail, setTaskDetail] = useState([])


    useEffect(() => {
        TaskService.getTaskById(id)
            .then(response => {
                setTaskDetail(response.data);
            })

    }, [id]) //This [id] avoid infinite loop of requests
    
    if (!taskDetail) return <div>No data</div>

    return (
        <div>
            <Detail taskDetail={taskDetail}/>
        </div>
    )
}

This class makes a request to the server and gather a data object. This object is then passed onto the Child Detail where it will be deserialized and visualized accordingly.

Child class

const Detail = ({ taskDetail }) => {


    return (
        <Box
            align='center'
            justifyContent='center'
            sx={{ width: '100%', marginTop: 4}}
            bgcolor=''
            //border='solid'
            >
            <Stack
                //border='solid'
                sx = {{width: '50%'}}
                justifyContent='center' 
                //border='solid'
                >
                <Typography
                    sx = {{ marginTop: 5}}
                    variant='h4'
                    fontWeight='bold'
                    bgcolor='#b2dafa'  
                    >NOMBRE DEL EJERCICIO<br/>{taskDetail.taskName}</Typography>
                    <Box
                        sx = {{ marginTop: 3}}
                        bgcolor='#b2dafa'
                    >
                        <Typography
                            variant='h5'
                            align='center'
                            sx = {{ margin: 2}}
                            fontWeight='bold'  
                            >DETALLES DEL EJERCICIO</Typography>
                        <Typography
                            sx = {{ margin: 2}}
                            variant='text'
                            border='#555'
                            >{taskDetail.details}
                            </Typography>
                    </Box>
                    <Box
                        sx = {{ marginTop: 5}}>
                    <Typography
                            variant='h6'
                            >Marca para completar</Typography><Toogle
                            label=''
                            toogled={false}
                            onClick={null}/>
                        <br></br>
                    </Box>
                    {taskDetail.id}
                    <Box
                        sx = {{ marginTop: 2}}>
                        <AddComment taskId={taskDetail.id}/>
                    </Box>
                    <Box
                        sx = {{ marginTop: 2}}>
                        <ListComments taskId={taskDetail.id}/>
                    </Box>
            </Stack>   
        </Box>
    )
}

As you can observe, this object is also passed to other child components. The context is that TaskDetail shows information and then offers two features, ListComments and AddComments. At the current moment, I am having an issue in AddComment where the prop taskId={taskDetail.id} is undefined.

Function in Child where I am having this issue

function ListComments(props) {

    const [comments, setComments] = useState([])

    useEffect(() => {
    
        console.log('DEBUG listcomments: '   props.taskId)
        TaskService.getTaskCommentsById(props.taskId)
            .then(response => {
                setComments(response.data)
            })
        
    }, [])

return (
        <div>
            <h2>Comentarios</h2>
            {comments.map((comment, _) => {    
                return  <Comment key={comment.id} comment={comment}/>
            })}
        </div>
)


}

I have noticed, that if I change something in the code and save it (re-renders the page). All of a sudden I get the atribute that I need instead of the undefined value.

How could I avoid this situation? I trust that I have made a huge mistake that I am unable to see, but its part of the learning. For this reason, I am open to suggestions.

CodePudding user response:

Since the data you get back from the service is an object I would suggest to initialize the state with an object {}.

const [taskDetail, setTaskDetail] = useState({});

In the ListComments component you can do the same as you did in the TaskDetail component. Run useEffect when the props.taskId changes. And add a early return if the taskId have no value yet.

useEffect(() => {
  console.log("DEBUG listcomments: "   props.taskId);

  if (!props.taskId) return;

  TaskService.getTaskCommentsById(props.taskId).then((response) => {
    setComments(response.data);
  });
}, [props.taskId]);

CodePudding user response:

Very cool that you're reaching out for help!

First, just a minor correction: They're not classes, they're functions / components.

I think the problem is the check condition at the top:

if (!taskDetail) return <div>No data</div>

Since taskDetail is initialised as an array, the condition will always be true since arrays are objects in javascript.

Because of this too, when you're passing it down, at least on the first render, none of these props in the lower components exist. So maybe try initalising it either as null, or changing the condition to the following:

if (!taskDetail || taskDetail.length === 0) return <div>No data</div>

One more thing, to make sure that the data is fetched, you need to add props.taskId to the dependency list in the List component.

  • Related