Let's build it.
$ mix phx.new hangman --no-ecto
$ cd hangman
$ mix phx.server
$ cd assets
$ rm static/images/phoenix.png
$ rm css/phoenix.css
$ npm install --save milligram
css/app.css
# remove @import "./phoenix.css"
@import "~milligram/dist/milligram";
add "resolve" block to webpack config:
//},
resolve: {
extensions: ['.js', '.jsx', '.css'],
},
//plugins: [
In lib/hangman_web/templates/layout/app.html.eex:
React is about having a data model and a function that renders it to an HTML DOM tree. When the data model changes, React re-renders for you.
This means that React gets full control of both the HTML content and event handling code for the portion of the page that is a React component.
(in assets)
$ npm install --save-dev @babel/preset-env @babel/preset-react
$ npm install --save react react-dom
$ npm install --save lodash jquery # common libraries
Add react preset to babel in webpack config:
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
In lib/hangman_web/templates/page/index.html.eex
Replace the contents with:
<div class="row">
<div class="column">
<h1>TODO</h1>
<div id="root">
React component loading...
</div>
</div>
</div>
Call your new component from assets/js/app.js:
// Add to bottom of app.js
import todo_init from "./todo";
window.addEventListener("load", (_ev) => {
let root = document.getElementById('root');
if (root) {
todo_init(root);
}
});
TODO state:
TODO rendering:
Bulleted list
toggle buttons
new item form.
Write todo.jsx
Create assets/js/hangman.jsx:
import React from 'react';
import ReactDOM from 'react-dom';
export default function hangman_init(root) {
ReactDOM.render(<Hangman />, root);
}
class Hangman extends React.Component {
constructor(props) {
super(props);
}
render() {
return <div>
<h2>Hangman loaded.</h2>
</div>;
}
}
Call your new component from assets/js/app.js:
// Add to bottom of app.js
import hangman_init from "./hangman";
window.addEventListener("load", (_ev) => {
let root = document.getElementById('root');
if (root) {
hangman_init(root);
}
});
The game:
The game state: