Skip to content

Instantly share code, notes, and snippets.

@arthurvi
Created October 5, 2020 09:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arthurvi/3cea4e0b1cfbc3288deac448281670f6 to your computer and use it in GitHub Desktop.
Save arthurvi/3cea4e0b1cfbc3288deac448281670f6 to your computer and use it in GitHub Desktop.
FullExample.jsx
import React from 'react';
const ItemListDispatch = React.createContext(null);
// Call our API here with id, otherIdForSavingOnly, value etc.
async function save(item) {
await new Promise((resolve) => setTimeout(resolve, 1000));
}
const itemsFromServer = {
'1': {
id: '1',
otherIdForSavingOnly: '1-1',
value: 'test',
isSaving: false
},
'2': {
id: '2',
otherIdForSavingOnly: '2-2',
value: 'another row',
isSaving: false
}
};
function reducer(currentItems, action) {
switch (action.type) {
case 'SET_VALUE':
return {
...currentItems,
[action.id]: {
...currentItems[action.id],
value: action.value
}
};
case 'START_SAVE':
return {
...currentItems,
[action.id]: {
...currentItems[action.id],
isSaving: true
}
};
case 'STOP_SAVE':
return {
...currentItems,
[action.id]: {
...currentItems[action.id],
isSaving: false
}
};
default:
throw new Error('Unknown action type');
}
}
const Item = React.memo(function Item({ id, value, isSaving, onSave }) {
const dispatch = React.useContext(ItemListDispatch);
console.log('render', id);
if (isSaving) {
return <li>Saving...</li>;
}
function onChange(event) {
dispatch({ type: 'SET_VALUE', id, value: event.target.value });
}
return (
<li>
<input value={value} onChange={onChange} />
<button onClick={onSave}>Save</button>
</li>
);
});
function ItemWrapper({ item }) {
const dispatch = React.useContext(ItemListDispatch);
const handleSave = React.useCallback(
async function handleSave() {
if (item.value.length < 5) {
alert('Incorrect length.');
return;
}
dispatch({ type: 'START_SAVE', id: item.id });
await save(item);
dispatch({ type: 'STOP_SAVE', id: item.id });
},
[item, dispatch]
);
return <Item id={item.id} value={item.value} isSaving={item.isSaving} onSave={handleSave} />;
}
function ItemList() {
const [items, dispatch] = React.useReducer(reducer, itemsFromServer);
return (
<ItemListDispatch.Provider value={dispatch}>
<ul>
{Object.values(items).map((item) => (
<ItemWrapper key={item.id} item={item} />
))}
</ul>
</ItemListDispatch.Provider>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment