Data Management
Programmatically add, update, and remove timeline entries using React state.
Example
Section titled “Example”import { useState } from 'react';
import { Timeline } from '@calendarjs/react';
export default function App() {
const [data, setData] = useState([
{ title: 'Project Started', date: '2025-01-01', borderColor: '#3498db' }
]);
const addEntry = () => {
setData([...data, {
title: 'New Entry',
date: '2025-02-01',
borderColor: '#e74c3c'
}]);
};
const updateFirst = () => {
if (data.length > 0) {
const updated = [...data];
updated[0] = { ...updated[0], title: 'Updated Entry', borderColor: '#2ecc71' };
setData(updated);
}
};
const removeLast = () => {
if (data.length > 0) {
setData(data.slice(0, -1));
}
};
return (
<div>
<button onClick={addEntry}>Add</button>
<button onClick={updateFirst}>Update</button>
<button onClick={removeLast}>Remove</button>
<Timeline data={data} align="left" />
</div>
);
}
Reference identity matters
Section titled “Reference identity matters”The wrapper diff-checks props with !==. Replacing the array (setData([...data, x])) re-renders; mutating in place (data.push(x)) does not — the reference hasn't changed. Always return a new array from your state updater.
App metadata on items
Section titled “App metadata on items”Items accept arbitrary keys via the ItemInput index signature — useful for joining timeline data to your domain model without casts:
import { useState } from 'react';
import { Timeline } from '@calendarjs/react';
export default function App() {
const [data, setData] = useState([
{ id: 101, title: 'Sprint 1', date: '2025-01-15', status: 'done' },
{ id: 102, title: 'Sprint 2', date: '2025-02-15', status: 'in-progress' },
]);
return (
<Timeline
data={data}
onEdition={(entry) => console.log('Edit', entry.id, entry.status)}
/>
);
}
Related
Section titled “Related”- Timeline Documentation
- Timeline Events
- Hooks —
useTimeline - TypeScript — typed metadata via
ItemInput