Designing Immutability Data Flows in Ember
-
Upload
jorge-lainfiesta -
Category
Technology
-
view
129 -
download
3
Transcript of Designing Immutability Data Flows in Ember
J O R G E L A I N F I E S T A
@jorgelainfiesta
Guatemala
India
Austria
HERACLITUS
PARMENIDESvs
• Original object remains.
• Handle properties through set and get.
• Encourages object mutation.
• Computed properties, observers.
T H E E M B E R O B J E C T ( PA RM EN I D E S )
• Never modify an object.
• Create new objects all the time.
• Different solutions due constrains.
T H E H E R A C L I T U S W A Y ( I MMU TA B I L I T Y )
• Tracking changes is easier.
• Simpler state management.
I M M U T A B L E D A T A F L O W S : W H Y ?
D E S I G N I N G
I M M U T A B L E D A T A F L O W S
I N E M B E R
J O R G E L A I N F I E S T A
• Simple form with text fields of
personal information.
• DDAU
B A S I C E X A M P L E
<label>Name:</label> {{one-way-input (get person 'name') update=(action 'update' 'name')}}
<br>
<label>Surname:</label> {{one-way-input (get person 'surname') update=(action 'update' 'surname')}}
<br>
<label>Email:</label> {{one-way-input (get person 'email') update=(action 'update' 'email')}}
t e m p l a t e s / c o m p o n e n t s / u s e r - f o r m . h b s
import Ember from 'ember';
export default Ember.Component.extend({ actions: { update(field, value) { this.get('onUpdate')(field, value); } } });
c o m p o n e n t s / u s e r - f o r m . j s
updateUser(field, value) { let user = this.get('user'); set(user, field, value); }
r e s p o n s i b l e p a r e n t
mutating object
updateUser(field, value) { let user = {...this.get('user')}; set(user, field, value); this.set('user', user); }
r e s p o n s i b l e p a r e n t
not mutating original object
updateUser(field, newData) { let user = this.get('user'); this.set('user', { ...user, [field]: newData }); }
r e s p o n s i b l e p a r e n t
Immutability
C O N T R A C T S F O R C O M P O S I T I O N
Update the parent with the same
data type that they provided.
C O N T R A C T S F O R C O M P O S I T I O N
interface ImmutableComponentProps<E> { value: E; onUpdate: (updatedValue: E) => void }
import Ember from 'ember';
export default Ember.Component.extend({ actions: { update(field, value) { this.get('onUpdate')({ [field]: value }); } } });
c o m p o n e n t s / u s e r - f o r m . j s
updateUser(newData) { let user = this.get('user'); this.set('user', { ...user, ...newData }); }
r e s p o n s i b l e p a r e n t
Immutability
{{user-form value=user onUpdate=(action 'updateUser')}}
r e s p o n s i b l e p a r e n t t e m p l a t e
W O R K I N G W I T H A R R A Y S
W O R K I N G W I T H A R R A Y S
★ map
★ reduce
★ filter
★ find
★ slice
• splice
• sort
• push
• Mutable array methods
in Ember
MutationsNo mutations
actions: { addItem(newElement) { let value = this.get('value'); this.get('onUpdate')([ ...value, newElement ]); }, removeItem(index) { let value = this.get('value'); this.get('onUpdate')([ ...value.slice(0, index), ...value.slice(index + 1) ]); } }
c o m p o n e n t s / t o d o - l i s t . j s
updateList(newList) { // Some treatment and processing? this.set('list', newList); }
r e s p o n s i b l e p a r e n t
{{todo-list value=list onUpdate=(action 'updateList')}}
r e s p o n s i b l e p a r e n t t e m p l a t e
C O M P U T E D P R O P E R T I E S
fullName: computed('user.{name,surname}', function() { return `${this.get('user.name')} ${this.get('user.surname')}`; })
r e s p o n s i b l e p a r e n t
fullName: computed('user', function() { return `${this.get('user.name')} ${this.get('user.surname')}`; })
r e s p o n s i b l e p a r e n t
N I C E F O R G L I M M E R
import Component, { tracked } from '@glimmer/component';
export default class ImmutabilityGlimmer extends Component { @tracked user = { name: 'Joe', surname: 'Schreier' };
@tracked('user') get fullName() { let { name, surname } = this.user; return `${name} ${surname}`; }
}
s o m e g l i m m e r c o m p o n e n t
updatePerson(personUpdate) { let { user } = this; this.user = { ...user, ...personUpdate }; }
s o m e g l i m m e r c o m p o n e n t
<simple-form @user={{user}} @onUpdate={{updatePerson}} />
s o m e g l i m m e r c o m p o n e n t
T H E F U T U R E ?
K E E P I N T O U C H !
J O R G E L A I N F I E S T A
@jorgelainfiesta
DMs are open :)