Search code examples
javascriptarraysreactjstraversalreact-hooks

How to access props from useEffect hook in Reactjs


I am fetching data from a news API and storing it in my state upon completion, then also passing the value of the state as props to a child component.

The data returned by the API is an array of objects. I only want to pass one element (object) of that array(which is now in my state) to my child component. So, I did just that by using the arrays conventional traversal method ([]) to pass one element, but unfortunately, when I tried using the useEffect hook in my child component to console log the props (which worked ), I was unable to access the properties of my element (object) from neither the hook nor from the body of the component as it kept on telling me that its undefined and that I have to cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. So I tried passing that one element as an array using the splice method in order to be traversed from the child component using the map method (which worked), however, I was still unable to access the properties from the useEffect hook.

Parent Component (Home.js)

 ...
const [data, setData]= useState([])
 useEffect(()=>{

        const fetch= async()=>{
            const response= await axios(url)
            const results= response.data
            setData(results.articles.slice(0,5))
        }
        fetch()

    },[url])

return(
    <>
    <Categories onClick={fetchCategory}/>
    <section className={classes.latest}>
    <Vertical postArray={data.slice(0,1)} postObject={data[0]}/>
    </section>
    </>
)
}

export default Home

Child component (Vertical.js)

const Vertical=(props)=>{

useEffect(() => {
    // console.log('postArray',props.postArray.title)
    console.log('postObject',props.postObject.title)

}, )

return(
    <>
    {/* <article key={props.postObject.content} className={classes.article}>
        <figure className={classes.article_figure}>
            <img src='' alt="article alternative"/>
        </figure>
        <div className={classes.article_details}>
            <h2>{props.postObject.title}</h2>
            <p>{props.postObject.description}</p>

        </div>
    </article> */}
    {props.postArray.map(post=>(
        <article key={post.content} className={classes.article}>
        <figure className={classes.article_figure}>
            <img src='' alt="article alternative"/>
        </figure>
        <div className={classes.article_details}>
            <h2>{post.title}</h2>
            <p>{post.description}</p>

        </div>
    </article>
    ))}
    </>
)
}

export default Vertical

The reason for this is that I need to access an URL which is inside the passed object in order to make another to fetch the thumbnail for that post.


Solution

  • you need to give dependencies to the useEffect, for it to watch and console

    useEffect(() => {
        // console.log('postArray',props.postArray.title)
        console.log('postObject',props.postObject.title)
    
    },[props.postObject.title]) //this will ensure that this prop is watched for changes
    

    Edit: for all those with undefined errors you can do the following change in the dependency

    useEffect(() => {
            // console.log('postArray',props.postArray.title)
            console.log('postObject',props?.postObject?.title) // optional-chaining would take care of the undefined check 
        
        },[props?.postObject?.title]) // optional-chaining would take care of the undefined check