'How can I prevent a child react component from rendering until I fetched id for slug?

Here data starts with a property posts that is an empty array. When it gets assigned a new property once I get slug, my Comments component re-render again with the new prop value, so that mean it re-render twice, how can I prevent a child component from rendering until I fetched id for slug

export const SinglePost = () => {

const { Content } = Layout;
const { Title, Paragraph, Text } = Typography;

const { slug } = useParams();


const [post, setPost] = useState({ posts: [] });

useEffect(() => {
axios.get(slug).then((res) => {
    setPost({ posts: res.data });
    console.log('a single post', res.data);
      });
}, [slug]);

let AuthorBlog = data.posts.author
let comment = data.posts.id


return (
      <>
<div className="container-fluid">
    <div className="row">
        <div className="col-12 col-md-8 col-lg-9">
            <SimpleBar style={{ maxHeight: '90%'}}>
                <Layout style={{ textAlign: 'center' }}>
                    <Content style={{ padding: '10rem 5% 2rem' }}>
                        <Image
                            className={ArticleCSS.Img}
                            src={data.posts.image}
                            preview={false}/>
                    <Layout>
                        <Typography className={ArticleCSS.info} >
                            <Title level={2} className={ArticleCSS.mainTitle}>{data.posts.title}</Title>
                            <Text>Created By: <Text strong className='writer'>{data.posts.author}</Text></Text>
                                <div className='dateDiv'><ClockCircleOutlined style={{color: 'rgb(59, 110, 145)',
                                        fontSize: '1.2rem', paddingRight: '0.6rem' }} />
                                <Text className='date'>On{" "}{moment(new Date(data.posts.published)).format("YYYY-MM-DD")}</Text></div>
                        </Typography>
                    </Layout>
                    <Layout className={ArticleCSS.ArticleContent}>
                        <Typography>
                            <Paragraph className={ArticleCSS.cardText}>{data.posts.content}</Paragraph>
                        </Typography>
                    </Layout>
                </Content>
            </Layout>
        <CommentComp id = {comment}/>
        <Comments id={comment} />
        </SimpleBar>
    </div>
    <div className={`col-12 col-md-4 col-lg-3 ${ArticleCSS.cold}`}>
        <RelatedBlog AuthorBlog = {AuthorBlog}/>
       </div>
     </div>
   </div> 
   </>
        );
        };

comments.js

export const Comments = (props) => {

console.log("Id post is:", props.id);

const [fetchComments, setFetchComments] = useState(true);
const [commentsList, setCommentsList] = useState([]);



useEffect(() => {
     axios.get(`comment/list/?blog_id=${props.id}`).then(
            (res)=> {
                setFetchComments(false);
                setCommentsList(res.data);
                console.log("from filter Commenst",res.data);
            },
            (err) => {
                console.error(err.response.data);
            }
        );

},[props.id]);


return (
  <div className='container'>
      <h5>Comments</h5>
      {fetchComments && <i>Loading...</i>}
      {!fetchComments && commentsList.length < 1 ? (
           <h5>No Comments for this Blog</h5> 
        ):(
            commentsList.map((item, key) => {
                return <CommentCard data={item} key={key} />
            })
        )}
    </div>

 )
 };

This image shows what I'm talking about. I don't want the child to render for the first time since I don't want to get with an undefined ID.



Solution 1:[1]

From what I've gathered so far it seems you don't want to render the Comments component until the id value is defined. For this you can use conditional rendering.

Example:

export const SinglePost = () => {
  const { slug } = useParams();
  const [post, setPost] = useState({ posts: {} });

  useEffect(() => {
    axios.get(slug).then((res) => {
      setPost({ posts: res.data });
      console.log('a single post', res.data);
    });
  }, [slug]);

  return (
    ...
    {!!post.posts.id && <Comments id={post.posts.id} />}
    ...
  );
}; 

Solution 2:[2]

I believe you'll need to wrap your axios call in an anonymous async function for it to behave as you intend. You can accomplish it with the following:

useEffect(() => {
  (async () => {
    await axios.get(slug).then((res) => {
      setPost({ posts: res.data });
      console.log('a single post', res.data);
    });
  })()
}, [slug]);

Give that a shot and let me know if it works!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Drew Reese
Solution 2 Amit Maraj