Closed Rec0iL99 closed 1 year ago
@sidmohanty11 let me know your thoughts on this. If approved, please assign the issue to me. Thanks.
@Rec0iL99 these are some really great points! I really like this idea. Let's start a discussion inside #embeddedchat channel.
Is this feature needs to be added @sidmohanty11 ? Please LMN. Thanks
Closed since we have solved the issue of multiple API calling. As an update: We have moved the API to its own package which uses real-time DDP communication for message updates, user status, UI interaction updates, and API fetching for message actions - start, pin ,delete report, edit, send
Thanks for the update @abhinavkrin
Currently we are using the
fetch
API and side effects (useEffect
) in components to fetch data from the RocketChat API and store the data like a cache in state management stores (Zustand). While this works, this can get complex in the future as new features get added and our state management size grows and complexity increases thus making maintenance of the code difficult.We also have issues where multiple API requests are made than needed (refer #112). This might not be a problem when RocketChat server is hosted locally, but when a user hosts their RocketChat server on the cloud on services like AWS/Digitaocean multiple hits to the server can be problematic. RocketChat might have a rate limiter, but still it is bad client wise.
How can React Query help us?
It replaces using traditional fetch with component side effects and custom state management to handle API calls!
React query uses custom hooks like the
useQuery
hook where you would need to pass in the async function that does the API call. The hook then would send a JS object with properties such asisLoading
,data
,error
. So now we don't need to check what the API request state is imperatively, react-query does the magic for us behind the scenes and returns the state such as, did the API call return an error (propertyerror
helps us here) etc.NOTE: Instead of fetch we can use any other APIs too like Axios, SuperAgent etc, which is pretty cool! NOTE:
useQuery
is forGET
requests anduseMutation
is forPOST
requests.How does it replace custom state management?
The first argument to the
useQuery
hook is thequeryKey
. This query key must be unique and it is a key that react-query uses to store our API calls data in a cache.Example in our case:
Previous Behaviour: To get the RocketChat messages for a particular channel we use the
api/v1/channels.messages
endpoint and send in a GET request. This returns our messages array and we store it in a zustand store.React-Query Behaviour: With react-query we can now use the
useQuery
hook to make our API call. Now after the request is successful, react-query will store the data in a cache using the query key we provided. Now if we want to get the messages in a different component, we can just use theuseQuery
hook again and except this time react-query won't make the API request instead it will search the cache and return us the data (messages). What if messages changed in the server? We can add cache timeouts which will invalidate the cache when the timeout is reached and react-query will have to make a request to the server to get the new data wheneveruseQuery
is called anywhere the next time.More details can be found in the React-Query docs. We can also do a lot of custom cache manipulation, but I think it is a thing for the future.
Addittional features:
If a query is called multiple times by a component, react-query will batch all the requests into one single request thus saving us a lot of API calls.
I have created a small component to illustrate this:
I clicked the count button which updates state multiple times in order to trigger a re-render of the component thus leading to multiple API calls but react-query batched it into one API call, but the
console.log
will happen because we are getting data from the cache as explained above.Not using react-query:
NOTE: Two API calls are done together because of
StrictMode
enabled in React for the development build.Current EmbeddedChat network calls