2020-04-03
Thoughts on reading through the hacker news response. 96 line version with JSX compiler.
js
objects)In this post, I'm going to make the smallest React-like thing that can do the above. It's very mithril influenced.
Here are sample applications: calendar picker, snake that use the library.
Lots of the code looks pretty code-golfy - I promise I don't do stuff like this at work, neither should you :-)
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:
'tr'
), with .
-separated class names{string: any}
object containing all the attributes to attach to the DOM nodeNoughts()
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')
m
work?Here's the source with and without comments.