Take this example from create triplit-app:
function useTodos() {
const todosQuery = Query('todos').Order('created_at', 'DESC');
const { results: todos, error, fetching } = useQuery(triplit, todosQuery);
return { todos, error, fetching };
}
export default function App() {
const [text, setText] = useState('');
const { todos, fetching } = useTodos();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await triplit.insert('todos', { text });
setText('');
};
return (
<div className="main-container">
<GettingStarted />
<div className="app-container">
<h1>Todos</h1>
<ConnectionStatus />
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="What needs to be done?"
className="todo-input"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button className="btn" type="submit" disabled={!text}>
Add Todo
</button>
</form>
{fetching && <p>Loading...</p>}
{todos && (
<div className="todos-container">
{todos?.map((todo) => <Todo key={todo.id} todo={todo} />)}
</div>
)}
</div>
</div>
);
}
In handleSubmit, if you try to read the value of todos immediately after the the insert, like so:
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await triplit.insert('todos', { text });
console.log('todo added', todos, fetching);
setText('');
};
the new todo will be missing from the value and you will get todo added [] instead of todo added [{ text: 'foo' }] like you ideally would. I believe this is related, because if I wait 20ms before console.log-ing the todos, I can see them :
|
this.db.onCommit( |
|
// @ts-expect-error |
|
throttle( |
|
async (tx) => { |
|
await this.db.updateQueryViews(); |
|
this.db.broadcastToQuerySubscribers(); |
|
await this.syncEngine.syncWrites(); |
|
}, |
|
20, |
|
{ leading: false, trailing: true } |
|
) |
|
); |
I also think
|
await this.ivm.bufferChanges(changes); |
|
for (const listener of this.onCommitListeners) { |
|
listener(changes); |
|
} |
|
return output; |
|
} |
may be related since the callback that actually updates query views is asynchronous, and all onCommitListeners are. I've done a bit of changing things trying to get things to work how I want it to, but I havent managed to find anything that has worked yet, and its kinda 2 am and I should sleep. So far I have tried:
- changing the throttling debounce to leading edge (doesnt work because the main thing is actually that its asynchronous I'm pretty sure)
- awaiting a Promise.all of the onCommitListeners listener callbacks
I can see how debounce is desirable, but if I await a db insert call I feel like my query views should be updated. I can do the
await triplit.db.updateQueryViews();
triplit.db.broadcastToQuerySubscribers();
myself manually, but that doesnt feel ideal.
Take this example from create triplit-app:
In handleSubmit, if you try to read the value of todos immediately after the the insert, like so:
the new todo will be missing from the value and you will get
todo added []instead oftodo added [{ text: 'foo' }]like you ideally would. I believe this is related, because if I wait 20ms before console.log-ing the todos, I can see them :triplit/packages/client/src/client/triplit-client.ts
Lines 134 to 145 in d3029ee
triplit/packages/db/src/db.ts
Lines 556 to 561 in d3029ee
I can see how debounce is desirable, but if I await a db insert call I feel like my query views should be updated. I can do the
myself manually, but that doesnt feel ideal.