'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>
)
};
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 |
