1

I am running into a performance issue that I don't know how to solve. I have a component structure like so (<PostDetail> being the parent component):

Data structure

Data in the post state that is passed through the PostContext (see below)

{
    "_id": "5eb1a5dd53ec08cdabca7ef3",
    [... more data]
    "description": "{blocks: Array(5), entityMap: {…}}",
    "likeCount": 6,
    "comments": "[{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, …]"
    isLikedByUser: true
}

On the following screen, you can see the chrome performance tab when I click on the "Like" button of my component, that updates the likeCount, which is only displayed in the <LikeCount> component.

Performance

When I click on the "Like" button, I send standard Axios post request and then, I update my post state that is passed through the PostContext using :

import { PostContext } from "../../../context/PostContext"
const [post, setPost] = useContext(PostContext)
[...]
setPost({ ...post, isLikedByUser: isLiked, likeCount: likeCount })

Nothing fancy here but, as you can see on the previous screenshot, the whole update takes about 300ms (it's even worse on a smartphone...), which is very bad for the user experience.

What can I do to only update the <LikeCount>, and not the other components inside <PostDetail> (<Description> or <Comments> for instance)

Etanor
  • 128
  • 8
  • 1
    Are you passing `likeCount` as a `prop` to **LikeCount** component from **PostDetail**? Are the components `Description/Comments` receive prop updates from **PostDetail**? Or all these components individually subscribe to Context updates via useContext? – Prathap Reddy Aug 02 '20 at 18:17
  • @PrathapReddy , I am not passing the likeCount as props. I am importing the ```PostContext``` in the `````` component, then declaring the ```const [post, setPost] = useContext(PostContext)``` (same thing for the ```Description/Comments``` ) and retrieving the ```likeCount``` as such : ```post.likeCount``` – Etanor Aug 02 '20 at 18:24
  • 1
    Since every component subscribed to Context, they will get all the related updates. That might not a problem in React perspective. When are you showing like count update is the question now. Are you showing updated count of likes upon successful API response. Does it seem a lag between user click and update of like? Is that your actual issue. Correct me if I interpreted wrongly – Prathap Reddy Aug 02 '20 at 18:30
  • 1
    I am actually updating the ```likeCount``` before making the api call for better user experience (if I recevive a ```code !== 200```, then I revert the changes and the set the likeCount to its previous value), and it was working fine. The problem is, as the number of comments on the post grows, the update takes more and more time to complete, and the frame per second drops to 1, which freezes the entire browser for 300ms in this case. – Etanor Aug 02 '20 at 18:38
  • Additionally, if you have to pass the data as props to all the children components, then why use useContext at all? My goal when I implemented the ```useContext``` was to avoid passing ```props``` to the whole component tree – Etanor Aug 02 '20 at 18:39
  • Ya... Am aware of the concept useContext and why you are using it here. Asked the question just to confirm. So now the problem is with more number of comments in the page like is having issues. I ran into similar issue in one of our app. Posting my answer assuming that it would help you in some way. – Prathap Reddy Aug 02 '20 at 18:48
  • Yes, the problem here are the comments which take almost 150ms to update... Is there a way to only subscribe to a specific value of the Context? – Etanor Aug 02 '20 at 18:52
  • What options do I have (besides adding a pagination for the comments, or passing the data as props and stop using the Context) to solve this issue? – Etanor Aug 02 '20 at 18:54
  • I guess there is no such option to subscribe specific value similar to `useSelector` in redux. You have the option of having **multiple Contexts** though. But the answer provide should help you. You don't need any pagination for comments. It worked for similar issue in our app. We have tested for 100 contact forms in a page (similar to comments in your app) where user is able to update every form without any issues. – Prathap Reddy Aug 02 '20 at 19:07
  • Hey, Have you found any viable solution for this performance issue? Curious to know the different approach if any – Prathap Reddy Aug 05 '20 at 12:59

1 Answers1

1

Since increasing number of comments causing issues with like of posts

I would recommend you to wrap the Comments component with React.memo (equivalent to shouldComponentUpdate in class component) which block unnecessary re-rendering of Comments if there are no updates to it.

Note: React.memo only checks for prop changes. If your function component wrapped in React.memo has a useState or useContext Hook in its implementation, it will still rerender when state or context change.

Infact, you can wrap all such components which don't need unnecessary rendering.

Remember the below statement from docs

Even though React only updates the changed DOM nodes, re-rendering still takes some time. In many cases it’s not a problem, but if the slowdown is noticeable, you can speed all of this up by overriding the lifecycle function shouldComponentUpdate, which is triggered before the re-rendering process starts.

Prathap Reddy
  • 1,688
  • 2
  • 6
  • 18
  • 1
    Thanks, I will try to do so tomorrow and mark your response as the answer if it works! – Etanor Aug 02 '20 at 19:20
  • Sure. But remember the **Note** point in answer. You can check the **Highlight Updates** button in **React Developer Tools** and see the component (Comments) updates before and after the above code change. – Prathap Reddy Aug 02 '20 at 19:25