function App() {
const { Container, Row, Col } = ReactBootstrap;
return (
);
}
function TodoListCard() {
const [items, setItems] = React.useState(null);
React.useEffect(() => {
fetch('/items')
.then(r => r.json())
.then(setItems);
}, []);
const onNewItem = React.useCallback(
newItem => {
setItems([...items, newItem]);
},
[items],
);
const onItemUpdate = React.useCallback(
item => {
const index = items.findIndex(i => i.id === item.id);
setItems([
...items.slice(0, index),
item,
...items.slice(index + 1),
]);
},
[items],
);
const onItemRemoval = React.useCallback(
item => {
const index = items.findIndex(i => i.id === item.id);
setItems([...items.slice(0, index), ...items.slice(index + 1)]);
},
[items],
);
if (items === null) return 'Loading...';
return (
{items.length === 0 && (
No items yet! Add one above!
)}
{items.map(item => (
))}
);
}
function AddItemForm({ onNewItem }) {
const { Form, InputGroup, Button } = ReactBootstrap;
const [newItem, setNewItem] = React.useState('');
const [submitting, setSubmitting] = React.useState(false);
const submitNewItem = e => {
e.preventDefault();
setSubmitting(true);
fetch('/items', {
method: 'POST',
body: JSON.stringify({ name: newItem }),
headers: { 'Content-Type': 'application/json' },
})
.then(r => r.json())
.then(item => {
onNewItem(item);
setSubmitting(false);
setNewItem('');
});
};
return (
);
}
function ItemDisplay({ item, onItemUpdate, onItemRemoval }) {
const { Container, Row, Col, Button } = ReactBootstrap;
const toggleCompletion = () => {
fetch(`/items/${item.id}`, {
method: 'PUT',
body: JSON.stringify({
name: item.name,
completed: !item.completed,
}),
headers: { 'Content-Type': 'application/json' },
})
.then(r => r.json())
.then(onItemUpdate);
};
const removeItem = () => {
fetch(`/items/${item.id}`, { method: 'DELETE' }).then(() =>
onItemRemoval(item),
);
};
return (
{item.name}
);
}
ReactDOM.render(, document.getElementById('root'));