visit
For example, let's say we have a
User
class defined as follows:class User {
constructor({firstName, lastName}) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}
class User {
// ...
View = () => {
return <div>{this.getFullName()}</div>;
};
}
const user = new User({firstName: 'Arthur', lastName: 'Rimbaud'});
Then, to render a
View
for this user
, we can do:<user.View />
This is a perfectly valid JavaScript/JSX code, and I don't think there is something wrong with it. Conceptually, the
View()
method is no different than the getFullName()
method. They are just methods returning a different kind of view: getFullName()
returns a string and View()
returns a React element.function UserView({user}) {
return <div>{user.getFullName()}</div>;
}
Then, to render
UserView
, we would do:<UserView user={user} />
It doesn't. Getting the models from a parameter or accessing them through
this
makes no difference. In both cases, models and views become tightly coupled.Some might argue that it is good to separate the model from the view because they are two different concerns. I don't get it. Again, how, in the object-oriented approach, the
getFullName()
method is different than the View()
method? Both are returning a representation of the model, so why should we separate them?It remembers me of the discussion about separating HTML and CSS. Yes, they serve two different purposes. HTML describes the content and CSS describes the presentation. But I don't think there is something wrong about putting them together in a cohesive way.Refactoring our previous example, we define the
User
model in a separate file:shared/user.js:
export class User {
constructor({firstName, lastName}) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}
web/user.js:
import {User as BaseUser} from '../shared/user.js';
class User extends BaseUser {
View = () => {
return <div>{this.getFullName()}</div>;
};
}
ios/user.js:
import {User as BaseUser} from '../shared/user.js';
class User extends BaseUser {
View = () => {
return <Text>{this.getFullName()}</Text>;
};
}
Physically, the code is then a bit more scattered, but logically, it is not. Whichever the platform, from a
User
instance, we have access to both the model (user.firstName
) and its views (<user.View />
).« Inheritance is evil. »
« Composition is the way to go. »I'm tired of hearing that all the time about anything and everything.Yes, single inheritance in static languages (Java, C#, etc.) may not be the right approach for composing the multiple pieces of an application. But it is not true with JavaScript where inheritance is dynamic, and therefore, extremely flexible.For example, we can use mixins to enable any kind of inheritance: multiple, conditional, parameterized, etc.There are many ways to implement mixins in JavaScript, but there is only one good way, and it is incredibly simple. Please for a nice explanation.
This article was originally published on the .