Git Product home page Git Product logo

react-3h's Introduction

react-3h

A simple implementation of React which I built in 3 hours for a job interview.

Motivation

As part of a job interview I was requested to implement a simple web app that displays real-time information in a table. I was requested not to use any frameworks and use only plain vanilla Javascript. To make it a bit more interesting, I decided to implement a very simple version of React. It took me 3 hours to develop it, hence the name.

I was so happy with the result that I decided to open-source it.

Install

$ npm install react-3h --save

Documentation

First I want to explain the basic concept of this implementation. The main idea behind this implementation is that components return html string, and it is all being compiled into a huge html string, that is being dumped into a given root element as innerHTML. This is a very simple implementation, but very inefficient. To make it a ittle better, I thought about implementing a very simple virtual DOM, or some mechainsm to compare DOM fragments and update it accordingly. Since I didn't want to put too much time into this job interview excercise, this was out of scope. Maybe I wil implement this later, again, just for fun.

While this approach is not for production, it might be relevant for server-side-rendering using node. The benefits of this framework is that it is very light, and do not rely on any external dependencies.

The whole framework is composed out of two modules: DOMManager and ComponentBase.

DOMManager

This a singelton class which is responsible to manage the actual rendering and to preserve instances of components. It expose the following functions:

renderApp(rootSelector, component, props)

This is the main function which you need to call to instantiate a react-3h app.

  • rootSelector: string - query selector to the app main root element.
  • component: Component - Component class which derives from Component.
  • props: Object - props to be set to the app.

setAppProps(props)

The App props can be used like a store for the entire app. You can update these props using this function. Calling this method will trigger a render action, which will render the entire app.

renderComponent(compoennt, key, props, children)

This method takes a component and generate an HTML for it.

  • component: Function | Component - the component to render. Components can be either stateless function or a class component.
  • key: string - since it was a bit challenge to associate an instance of a component to its actual DOM, i decided to simplify it and require a unique key for each component instance, so I will know to match them. It is actually only important for components who preserve state.
  • props: Object - the component props. You can access them using this.props like in react.
  • children: string - children of the component. You can access it using this.props.children like in react.

renderComponentSnapshot(component, props, children)

This is a helper function to render a component for testing purposes, to get the component html string, without invoking all the internal mechinism for components. It can be used with jest, for example:

test('Component can be rendered correctly', () => {
  expect(DOMManager.renderComponentSnapshot(MyComponent)).toMatchSnapshot();
});

Component

Like in react, a component can wither be a stateless function or a stateful class. If you implement a stateless function all you need to do is to define a function that gets props and return html string.

Here is an example:

// Title.js
export default ({ children, className }) => `<h1 class="${className}">${children}</h1>`;

In case you need a stateful component you need to derive from the Component class and at least implement the render method which return an html string.

First you need to extend Component:

import { Component } from 'react-3h';

class Loading extends Component {}

Like in react there are also familiar concepts that are available:

  • this.props will give you access to the props.
  • this.props.children - will give you access to the children of this component that needs to be rendered (this is a string)
  • componentWasRendered - if you implement this function it will be called after each render. After this function call you can use getRootElement and find
  • getRootElement - return the dom element of the root of the component. This is only available after componentWasRendered or componentWasMounted. caution: you should not store the reference to the DOM element since it is changed after each render
  • find - executing querySelector from the getRootElement method to find some element inside the component.
  • componentWasMounted - if you implement this function it will be called when the component was mounted.
  • componentWasUnmounted - if you implement this funciton it will be called after the component was unmounted.
  • setState - allows you to update the state of the component. After caling this method it will trigger a render of the whole app.

Example

Lets see an example of a simple app

app.js

import { Component, renderComponent, renderApp, setAppProps } from 'react-3h';
import Loading from './components/Loading';
import Title from  './components/Title';
import Status from './components/Status';

const store = {
  wasInit: false,
  data: {},
};

class App extends Component {
  render() {
    return `
      <div class="content">
        ${renderComponent(Title,"main-title",{}, `
          <span>${children}${renderComponent(Status, 'status')}</span>
        `)}
        ${this.renderContent()}
      </div>
    `;
  }

  renderContent() {
    const { wasInit } = this.props;

    if (!wasInit) {
      return renderComponent(Loading, "loading");
    }

    return `
      <div>
        ${renderComponent(Content, "content", { data: this.props.data })}
      </div>
    `;
  }
}

renderApp("#root", App, store);

fetch('/data').then(response => response.json).then(data => {
  store.wasInit = true;
  store.data = data;
  setAppProps(store);
});

Loading.js

import { Component } from 'react-3h';

class Loading extends Component {
  constructor(props) {
    super(props);
    this.state = {
      dots: '...',
    };
  }

  render() {
    return `<h1>Loading${this.state.dots}</h1>`;
  }

  componentWasMounted() {
    this.interval = setInterval(() => {
      let dots = `${this.state.dots}.`;
      if (dots.length > 3) {
        dots = '.';
      }
      this.setState({dots});
    }, 1000);
  }

  componentWasUnmounted() {
    clearInterval(this.interval);
  }
}

export default Loading;

Title.js

export default ({ children, className }) => `<h1 class="${className}">${children}</h1>`;

react-3h's People

Contributors

mrharel avatar

Watchers

 avatar  avatar  avatar

Forkers

596050

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.