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);
Made with Slides.com