Edit Modal (Save/Cancel)
Pattern for if you want to have a modal that can either add a new instance of an object or edit an existing one. The parent copy of the object won't be updated until you press "Save".
Live Editor
function App() { interface IPerson extends ICopy, IDefault { name: string; age: number; } const copy = function copy(person: IPerson): IPerson { return { name: person.name, age: person.age }; } const getDefault = function getDefault(person: IPerson): IPerson { return { name: "", age: 0 }; } // // Edit Modal // interface IEditModalProps { person: IPerson | null; onSave: (person?: IPerson) => void; onCancel: () => void; } function EditModal(props: IEditModalProps) { const [localPerson, setLocalPerson] = useState<IPerson | undefined>(undefined); useEffect(() => { if (props.person) { setLocalPerson(copy(props.person)); } else { setLocalPerson(getDefault()); } }, [props.person, setLocalPerson]); const onPropertyChange = useCallback((property: string, value: any) => { setLocalPerson({ ...localPerson, [property]: value }); }, [localPerson]); if (!localPerson) { return null; } return ( <div> Local Person: <code>{JSON.stringify(localPerson)}</code> <br /> <input type="text" value={localPerson.name} onChange={(e) => { setLocalPerson({ ...localPerson, name: e.target.value }) }} /><br /> <input type="number" value={localPerson.age} onChange={(e) => { setLocalPerson({ ...localPerson, age: e.target.value }) }} /><br /> <button type="button" onClick={()=> { props.onSave(localPerson); }}>Save</button>{' '} <button type="button" onClick={props.onCancel}>Cancel</button> </div> ); } // // App // const [person, setPerson] = useState<IPerson | null>({ name: "John", age: 30 }); // const [person, setPerson] = useState<IPerson | null>(null); return ( <div> Parent Copy: <code>{JSON.stringify(person)}</code><br /> <EditModal person={person} onSave={setPerson} /> </div> ) }
Result
Loading...