Detect new todos
We will use GraphQL subscriptions to get notified if there are any new public tasks added. Whenever, a notification is received, we will fetch the tasks newer than the newest task in local state.
We wish to show the newTodosBanner
saying New tasks have arrived
only when a notification has been received.
We will wrap the parent component src/todo/TodoPublicWrapper.re
with a Subscription
and pass the the newestId
in the database as a prop to the TodoPublicList
component. Looking at this newestId
, we will check if it is greater than the id
of the newest visible todo. If it is, we know that a new task(s) are present in the database and we show the banner saying New tasks have arrived
.
Lets first define the subscription in src/GraphQLQueries.re
. Add the following code to the bottom.
module NotifyNewPublicTodos = [%graphql{|subscription notifyNewPublicTodos {todos (where: { is_public: { _eq: true}}, limit: 1, order_by: {id: desc }) {id}}|}];module NotifyNewPublicTodosSubscription = ReasonApollo.CreateSubscription(NotifyNewPublicTodos);
Now, use this NotifyNewPublicTodosSubscription
component in TodoPublicWrapper
to wrap TodoPublicList
. Go to src/todo/TodoPublicWrapper
and make the following changes:
<ReasonApollo.Consumer>...{client => {- <TodoPublicList client={client}/>+ <GraphQLQueries.NotifyNewPublicTodosSubscription>+ ...{+ ({result}) => switch(result) {+ | Error(error) => {+ Js.Console.error(error);+ <div> {ReasonReact.string("Error")}</div>+ }+ | Data(data) => {+ let todos = data##todos;+ let latestTodoId = if (Array.length(todos) > 0) { todos[0]##id } else { 0 };+ <TodoPublicList client={client} latestTodoId={latestTodoId}/>+ }+ | Loading => {+ <TodoPublicList client={client} latestTodoId={0}/>+ }+ }+ }+ </GraphQLQueries.NotifyNewPublicTodosSubscription>}}</ReasonApollo.Consumer>
We are making the subscription for the newest task in the database and pass the newest id as a prop called latestTodoId
.
Now, in src/todo/TodoPublicList.re
, make the make
function accept latestTodoId
as a prop.
-let make = (~client) => {+let make = (~client, ~latestTodoId) => {
Now, compute a boolean variable called shouldShowNewTodosBanner
which decides if there are new todos in the database. Based on shouldShowNewTodosBanner
, show or hide the newTodosBanner
.
- <div className={"loadMoreSection"}>- {ReasonReact.string("New tasks have arrived!")}- </div>+ let existingTodoLength = Array.length(state##todos);+ let latestVisibleId = if (existingTodoLength > 0) { state##todos[0]##id } else { 0 };+ let shouldShowNewTodosBanner = latestVisibleId < latestTodoId;+ let newTodosBanner = if(shouldShowNewTodosBanner) {+ <div className={"loadMoreSection"}>+ {ReasonReact.string("New tasks have arrived!")}+ </div>+ } else {+ {ReasonReact.null}+ };
Once you do this, whenever there is a new public task in the database, the new todos banner would be displayed. Try entering a new public todo; your own todo will also be treated as a new todo in the database and the banner would be displayed.
In the next section, we will implement the onClick
handler of this banner i.e we will sync the new todos in the database with the local todos.
- Build apps and APIs 10x faster
- Built-in authorization and caching
- 8x more performant than hand-rolled APIs