DavidKim
DavidKim2mo ago

How does the convex dashboard animate data change?

When we update the document in convex dashboard, the dashboard is able to animate the changed cell. and this works across all clients. How is it able to detect a data change (assuming the dashboard uses convex as the backend)
9 Replies
lee
lee2mo ago
@ari is very good at React. Snippet:
const previousValue = usePrevious(value);
const [didJustChange, setDidJustChange] = useState(false);


useEffect(() => {
if (
// Don't highlight changes if the row is rendering for the first time,
isRowMounted &&
// Don't highlight if the cell is rendering for the first time
!mounted &&
// Don't highlight changes if the row layout has been changed due to a change in
// document count.
!didNumberOfRowsChange &&
// Highlight rows when the value changes
rowId === previousRowId &&
!isEqual(value, previousValue)
) {
setDidJustChange(true);
// To reset the animatation, reset the state after one second.
setTimeout(() => setDidJustChange(false), 1000);
}
}, [
rowId,
previousRowId,
previousValue,
value,
isRowMounted,
mounted,
didNumberOfRowsChange,
]);


...
className={classNames(
// Show a border on the right side while animating to prevent the background highlight
// from overlapping other cells
didJustChange && "animate-highlight border-r",
"font-mono text-xs text-content-primary",
"w-full h-full flex items-center focus:outline-none",
"focus:ring-1 focus:ring-border-selected text-left",
!isEditable && "cursor-default",
)}
const previousValue = usePrevious(value);
const [didJustChange, setDidJustChange] = useState(false);


useEffect(() => {
if (
// Don't highlight changes if the row is rendering for the first time,
isRowMounted &&
// Don't highlight if the cell is rendering for the first time
!mounted &&
// Don't highlight changes if the row layout has been changed due to a change in
// document count.
!didNumberOfRowsChange &&
// Highlight rows when the value changes
rowId === previousRowId &&
!isEqual(value, previousValue)
) {
setDidJustChange(true);
// To reset the animatation, reset the state after one second.
setTimeout(() => setDidJustChange(false), 1000);
}
}, [
rowId,
previousRowId,
previousValue,
value,
isRowMounted,
mounted,
didNumberOfRowsChange,
]);


...
className={classNames(
// Show a border on the right side while animating to prevent the background highlight
// from overlapping other cells
didJustChange && "animate-highlight border-r",
"font-mono text-xs text-content-primary",
"w-full h-full flex items-center focus:outline-none",
"focus:ring-1 focus:ring-border-selected text-left",
!isEditable && "cursor-default",
)}
Also import { usePrevious } from "react-use"
ari
ari2mo ago
Outside of the react tricks, as you mentioned the real magic here is that the dashboard is powered by convex, so the "system" query that loads of documents for the data page gets re-run whenever any of your clients change the data the query is subscribed to The underlying Convex code for system queries is open-source! https://github.com/get-convex/convex-backend/blob/main/npm-packages/system-udfs/convex/_system/frontend/paginatedTableDocuments.ts
DavidKim
DavidKimOP2mo ago
❤️ I noticed you have condition checks to prevent highlighting if row is being rendered for the first time but in the dashboard, if i add a new document (a row is being rendered for the first time), it is highlighted -- is there a way you are distinguishing between a new document being added vs rows being rendered for the first time?
ari
ari2mo ago
Row highlighting happens in the component that renders all the cells, so that one does highlight the entire row on mount The code in the cell component is making sure we don't highlight the entire row and all the cells inside of it when a new document is added
DavidKim
DavidKimOP2mo ago
ahh thank you! I am still curious how you could distinguish between the row rendering for the first time (say on refresh, or when you open the page) vs a row being added via document adding? because I see that when i refresh the page, no highlights go off. (Sorry for so many questions!! really appreciate the help)
ari
ari2mo ago
No worries at all! Are you building something similar to the data page on the convex dashboard? Here's a snippet from how we decide to highlight new rows:
const previousRowId = previousRow?.values._id;

const [didJustCreate, setDidJustCreate] = useState(false);
useEffect(() => {
// The entire row should be highlighted if the row was recently created and
// not already rendered.
if (!previousRowId && Date.now() - row.values._creationTime < 1000) {
setDidJustCreate(true);
// To reset the animatation, reset the state after one second.
setTimeout(() => setDidJustCreate(false), 1000);
}
}, [row, previousRow, previousRowId, _id]);
const previousRowId = previousRow?.values._id;

const [didJustCreate, setDidJustCreate] = useState(false);
useEffect(() => {
// The entire row should be highlighted if the row was recently created and
// not already rendered.
if (!previousRowId && Date.now() - row.values._creationTime < 1000) {
setDidJustCreate(true);
// To reset the animatation, reset the state after one second.
setTimeout(() => setDidJustCreate(false), 1000);
}
}, [row, previousRow, previousRowId, _id]);
DavidKim
DavidKimOP2mo ago
yeah similar ! im building ~ something like an airtable ~ and wanted to do fun animations when data changes thank you so much!!! ahhh you use the creationtime! smart smart
ari
ari2mo ago
Yup, being a little creative with that one -- since it can be hard to know if the document was added or just got added to the result of your convex query (we're using pagination on the data page, so new rows appear all the time) I might actually snag your idea from the other thread you made so that we start animating when documents get deleted, hope you don't mind 😉
DavidKim
DavidKimOP2mo ago
of course i dont mind! ❤️ thank you for the helppp

Did you find this page helpful?