in ,

React in 33 lines, Hacker News

         

         React         

you pass in a function that

  • takes state and returns a virtual DOM (just a tree of plain ol ‘ js objects)             
  • it renders that virtual DOM as a real
    DOM in the browser             

  • if you change the state, it runs the function again, this returns a new virtual DOM
  •             

  • It efficiently updates the real DOM so that it matches the new virtual DOM                  It also does a load of other crap as well, but we’re going to ignore that.          

            In this post, I’m going to make the smallest React-like thing that can do the above. It’s very mithril influenced.     

        

            Here is a sample calendar picker application that uses the library .     

        

             Lots of the code looks pretty code-golfy – I promise I don’t do stuff like this at work, neither should you: -)     

        

    Noughts and crosses

        

            We’re going to make this noughts and crosses game:         

             

            Now let’s look at the code to this, you can also just view the page source if you want.     

        

     let currentPlayer='o' let winner=null const g=[['', '', ''], ['', '', ''], ['', '', '']] // grid  const move=(value, i, j)=> {     // ... game logic goes here     renderNoughts () }  const Cell=(value, i, j)=> m ('button.cell',     {onclick: ()=> move (value, i, j)}, value ) const Noughts=()=> m ('',     winner         ? m ('marquee', `winner: $ {winner}`)         : m ('h3', `current player: $ {currentPlayer}`),     m ('table', g.map (         (row, i)=> m ('tr', row.map (             (value, j)=> m ('td', {class: value}, Cell (value, i, j)))))), )  const renderNoughts=()=> m.render (     document.getElementById ('noughts'),     {children: [Noughts()]}, ) renderNoughts ()        

    Cute, so what's going on?

        

    First we defined some state:

        
     let currentPlayer='o' let winner=null const g=[['', '', ''], ['', '', ''], ['', '', '']] // grid       

    These hold the state of our game, we will mutate them.

        
     const move=(value, i, j) {...}  
         

    This function makes a move in the game, it takes 'x' or 'o' along with 2 integer coordinates. It will mutate all the state variables to reflect the new state of the game. After that, it calls renderNoughts () , this is a call to rerender the game - but we'll come back to that.

        

    Next we define the functions that return virtual DOMs, Noughts and Cell .

        

            The m (...) calls take:         

    a tag name (eg . 'tr' , with
  • – separated class names
  •             

  • (optionally) a {string: any} object containing all the attributes to attach to the DOM node             
  • an arbitrarily nested list of (children - these are other virtual DOM nodes or strings of text
  •                  And return virtual DOM elements, for example, calling Noughts () would return:          

    {{     tag: 'div',     attrs: {},     classes: [],     children: [         {             tag: 'h3',             attrs: {},             classes: [],             children: [ 'current player: x' ]         },         {             tag: 'table',             attrs: {},             classes: [],             children: [                 {                     tag: 'tr',                     attrs: {},                     classes: [],                     children: [ ...

        

    Next we make the function renderNoughts () , when you call it, it will call our Noughts function, and attempt to efficiently render the resulting virtual DOM onto document.getElementById (‘noughts’)

        

    How does

  • m work?

        

            Here’s the source with

    and without

  • comments.      Read More