Component class

The Component class will be the bread and butter of our dynamic UI. Let’s write an minimal
implementation:

  1. index.js
  2. ...
  3. class Component {
  4. constructor(props) {
  5. this.props = props || {};
  6. }
  7. setState(partialNewState) {
  8. // Awesome things to come
  9. }
  10. //will be overridden
  11. render() {}
  12. }

Exciting! We’re going to implement the much used setState function ourselves!
But, before we’re going finish the Component class implementation we will we look at mounting first.
We will definitly run into some problems, but these problems will
let us define the requirements for the Component class better!

Mounting a Component with mountVComponent.

As you probably could have guessed we’re going to define
this function as mountVComponent. And it does a bit more work then
the other mount functions. Let’s see:

  1. index.js
  2. ...
  3. function mountVComponent(vComponent, parentDOMNode) {
  4. const { tag, props } = vComponent;
  5. // build a component instance. This uses the
  6. // defined Component class. For brevity
  7. // call it Component. Not needed ofcourse, new tag(props)
  8. // would do the same.
  9. const Component = tag;
  10. const instance = new Component(props);
  11. // The instance or Component has a render() function
  12. // that returns the user-defined vNode.
  13. const currentElement = instance.render();
  14. // the currentElement can be a vElement or a
  15. // vComponent. mountVComponent doenst't care. Let the mount()
  16. // handle that!
  17. const dom = mount(currentElement, parentDOMNode);
  18. //save the instance for later
  19. //references!
  20. vComponent._instance = instance;
  21. vComponent.dom = dom;
  22. //append the DOM we've created.
  23. parentDOMNode.appendChild(dom);
  24. return dom;
  25. }

React.js has a mountComponent function on it’s ReactCompositeComponent or ReactDOMComponent.

The most important part is that we instantiate our Component with new Component(props).
This creates a Component class, that has a render() function.
The render function returns the vNodes and, we recurse again!
It’s all about recursion yo!

Now we need to update the mount function, so that it can handle vComponents.

  1. index.js
  2. ...
  3. function mount(input, parentDOMNode) {
  4. if (typeof input === 'string' || typeof input === 'number') {
  5. //we have a vText
  6. return mountVText(input, parentDOMNode);
  7. }
  8. else if (typeof input.tag === 'function') {
  9. //we have a component
  10. return mountVComponent(input, parentDOMNode);
  11. }
  12. // for brevity make an else if statement. An
  13. // else would suffice :).
  14. else if (typeof input.tag === 'string') {
  15. //we have a vElement
  16. return mountVElement(input, parentDOMNode)
  17. }
  18. }

And we can define and render our new application as:

  1. class App extends Component {
  2. render() {
  3. return createElement('div', { style: { height: '100px', background: 'red'} }, [
  4. createElement('h1', {}, [ this.props.message ])
  5. ]);
  6. }
  7. }
  8. const root = document.body;
  9. mount(createElement(App, { message: 'Hello there!' }), root);

If the code is not working, or If I accidently skipped parts, please let me know. The
code we should have at this point. can be found here

Awesome! We’ve now introduced Components!. We’ve built a Component Class
which we can easily extend. We’re making moves yoo!
But, we’re not utilizing the Components as we should, we introduced them for their powers..

Let’s take a look at state.