Setters - Raiondesu/Tuex GitHub Wiki

In a traditional Flux architecure, store values (i.e. "state") can be changed only through so called mutations.

Tuex has a simpler alternative to it: setters.

A Native JavaScript Concept

As the most of Tuex's concepts, setters are already a part of a modern JavaScript.

const obj = {
  firstname: 'John',
  lastname: 'Smith',

  set FullName(value) {
    const name = value.split(' ');
    this.firstname = name[0];
    this.lastname = name[1];
    console.log(this.firstname);
    console.log(this.lastname);
  }
}

obj.FullName = 'Evan You';
// => 'Evan'
// => 'You'

Tuex-Enhanced Setters

As it was with getters and values, setters in Tuex are plain JS setters, that can reference their context as this.

Similar to getters, Tuex tracks everything that is done inside of the setter:

const tuex = new Tuex.Store({
  num: 0,
  set Num(value) {
    this.num = value;
  }
});

tuex.store.Num = 10;

In this example Tuex knows that the setter Num was called with the argument 10 and that it has assigned 10 to num.

"Why plain JS setters?"

I hear you say.

Well, most Flux implementations (including Vuex) use functions to call "mutation handlers" (which are also functions). The thing with these handlers is that they MUST be synchronous in order to keep the whole store predictable (which is the very reason the Flux pattern exists).

And this is the problem for a JS-programmer. This is the pitfall of any JS Flux implementation, because functions in JS, even though synchronous by default, tend to become asynchronous very easily. And it's the final developer's pain to know how to prevent this from happening. This is also the very reason Tuex exists.

Tuex uses setters in a much more predictable fashion, as it is much harder for the setters' code to run asynchronously, so the developer would never even think about that problem anymore.

In the future versions it's planned that Tuex will synchronize the setters' code, so this will be even less of a problem.

Common misconception

This is a common thought within the JavaScript community, that setters are wrong and should not be used anywhere. And except the fact that the JS community likes to just ban valid language features quite often, there's still a reason to this.

The thing with setters is that in case of misspelling their names

obj.FulName = 'Mike Johnson',

the JavaSvript interpreter will just add the misspelled property (FulName) to the original object without any exceptions or warnings.

Tuex has a protection from such a case, as the store object is sealed and can be rewritten only through the replaceStore function.

Property-Merging And Pseudo-Values

In plain JavaScript a getter and a setter that have the same name are combined into a pseudo-property: an object's field that behaves like a normal property, but functions differently under the hood.

The same is true for Tuex - a pair of a getter and a setter with the same name behaves like a value:

const tuex = new Tuex.Store({
  firstname: 'John',
  lastname: 'Smith',

  set FullName(value) {
    const name = value.split(' ');
    this.firstname = name[0];
    this.lastname = name[1];
  }
  get FullName() {
    return this.firstname + ' ' + this.lastname;
  }
})

console.log(tuex.store.FullName);
// => John Smith

tuex.store.FullName = 'Evan You';
// => firstname: 'Evan'
// => lastname: 'You'

This also means that the before-mentioned pair becomes enumerable:

JSON.stringify(tuex.store);
// => { "firstname": "Evan", "lastname": "You", "FullName": "Evan You" }

Such an approach also allows to make enumerable getters just by adding an empty setter with the same name to the store:

const tuex = new Tuex.Store({
  firstname: 'John',
  lastname: 'Smith',

  set FullName(value) {}
  get FullName() {
    return this.firstname + ' ' + this.lastname;
  }
})

// Getter 'FullName' is now enumerable without adding unwanted functionality:
Object.keys(tuex.store);
// => [ 'firstname', 'lastname', 'FullName' ]