Distinguish Class and Function in React
Define Component
// function
function HelloWord() {
return <p>Hello Word</p>;
}
// class
class HelloWord extends React.Component {
render() {
return <p>Hello Word</p>;
}
}
Define Component
// by using function
function HelloWord() {
return <p>Hello</p>;
}
const result = HelloWord(props);
// by using class
class HelloWord extends React.Component {
render() {
return <p>Hello</p>;
}
}
const instance = new HelloWord(props); // HelloWord {}
const result = instance.render(); // <p>Hello</p>
why it’s important to treat functions and classes differently
new Person() | Person() | |
---|---|---|
class | "this" is a Person instance | TypeError |
function | "this" is a Person instance | "this" is "window" or "undefined" |
With or Without New
1. React could just use new on every call?
1. `this` is bind in function scope but we do not need it.
function HelloWord() {
return <p>Hello</p>;
}
new HelloWord();
2. arrow function
const HelloWord = () => <p>Hello</p>;
new HelloWord(); // Error
// this is resolved from the closest regular function
class Friends extends React.Component {
render() {
const friends = this.props.friends;
return friends.map(friend =>
<Friend
// `this` is resolved from the `render` method
size={this.props.size}
name={friend.name}
key={friend.id}
/>
);
}
}
// arrow functions don’t have their own
3. preclude React from supporting components that return strings or other primitive types
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
2. Detect React.Compoment descendants?
// class
class A {}
class B extends A {}
console.log(B.prototype instanceof A); // true
Prototype Chain in new Object
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() {
alert('Hi, I am ' + this.name);
}
var stanney = new Person('Stanney');
// Sets `stanney.__proto__` to `Person.prototype`
stanney.sayHi();
// 1. Does stanney have a sayHi property? No.
// 2. Does stanney.__proto__ have a sayHi property? Yes. Call it!
stanney.toString();
// 1. Does stanney have a toString property? No.
// 2. Does stanney.__proto__ have a toString property? No.
// 3. Does stanney.__proto__.__proto__ have a toString property? Yes. Call it!
Prototype Chain in new Object
class HelloWord extends React.Component {
render() {
return <p>Hello</p>;
}
}
let c = new HelloWord();
console.log(c.__proto__); // HelloWord.prototype
console.log(c.__proto__.__proto__); // React.Component.prototype
console.log(c.__proto__.__proto__.__proto__); // Object.prototype
c.render(); // Found on c.__proto__ (HelloWord.prototype)
c.setState(); // Found on c.__proto__.__proto__ (React.Component.prototype)
c.toString(); // Found on c.__proto__.__proto__.__proto__ (Object.prototype)
Prototype Chain in React
// `extends` chain
HelloWord
→ React.Component
→ Object (implicitly)
// `__proto__` chain
new Greeting()
→ Greeting.prototype
→ React.Component.prototype
→ Object.prototype
Prototype Chain in React
Prototype Diagram in Foo
function Foo(x) {
this.x = x;
this.y = 432;
}
Foo.prototype.point = function() {
return `Foo ${this.x + this.y}`;
}
var myfoo = new Foo(99);
console.log(myfoo.point());
class Base {
foo() {return 'foo in Base';}
bar() {return 'bar in Base';}
}
class Child extends Base {
foo() {return 'foo in Child';}
whiz() {return 'whiz in Child';}
}
const b = new Base;
const c = new Child;
console.log(b.foo()); // foo in Base
console.log(b.bar()); // bar in Base
console.log(c.foo()); // foo in Child
console.log(c.bar()); // bar in Base
console.log(c.whiz()); // whiz in Child
Prototype Diagram in Base and Child
Seem like this is solution, but not what React does though
Reason
instance of doesn’t work when there are multiple copies of React on the page
What React Do
// Inside React
class Component {}
Component.isReactClass = {};
// We can check it like this
class Greeting extends Component {}
console.log(Greeting.isReactClass); // ✅ Yes
What React Do Now
// Inside React
class Component {}
Component.prototype.isReactComponent = {};
// We can check it like this
class Greeting extends Component {}
console.log(Greeting.prototype.isReactComponent);
Distinguish Class and Function in React
By Stanney Yen
Distinguish Class and Function in React
- 274