This is my 11th write up on dev.to site. MithrilJS component and state management. A substantial part of the code was written by AI. Source code included.
MithrilJS
Mithril is an excellent JS framework, tiny and powerful. Like with another JS frameworks you can write components - a small piece of code solving a dedicated subtask.
State management
Most of applications and most of JS frameworks implement state management - the way state is realized and maintained.
There are many ways to implement state management in Mithril. Excellent source of information is a blog post of Kevin Fiol: Simple State Management in Mithril.js
Component
In this example I have SVG component, logical OR gate. It has two inputs (A, B) and one output (Q).
You can intend either internal component state (so component is independent) or global app state. And this is what I show you in this example.
State
const NodeState = (size) => Array(size).fill(false);
const NodeActions = (state) => ({
setNode: (index, value) => {
if (index >= 0 && index < state.length) {
state[index] = value;
m.redraw(); // Ensure Mithril redraws the view to reflect state changes
}
}
});
OR gate
const ORGate = {
view: ({ attrs: { state, actions, idxA, idxB, idxQ } }) => {
const inputA = state[idxA];
const inputB = state[idxB];
const output = inputA || inputB;
// Update the output node state
actions.setNode(idxQ, output);
return m('div',
m('svg', {
viewBox: '0 0 100 100',
width: '100',
height: '100',
xmlns: 'http://www.w3.org/2000/svg'
},
[
// Input lines
m('line', { onclick: () => actions.setNode(idxA, !inputA), x1: '0', y1: '30', x2: '30', y2: '30', stroke: inputA ? 'red' : 'blue', 'stroke-width': '2' }),
m('line', { onclick: () => actions.setNode(idxB, !inputB), x1: '0', y1: '70', x2: '30', y2: '70', stroke: inputB ? 'red' : 'blue', 'stroke-width': '2' }),
// OR gate rectangle
m('rect', { x: '30', y: '20', width: '40', height: '60', fill: 'none', stroke: 'black', 'stroke-width': '2' }),
// Output line
m('line', { x1: '70', y1: '50', x2: '100', y2: '50', stroke: output ? 'red' : 'blue', 'stroke-width': '2' }),
// Labels for inputs and output
m('text', { onclick: () => actions.setNode(idxA, !inputA), x: '13', y: '25', 'text-anchor': 'middle', 'font-size': '12' }, 'A = ', inputA ? '1' : '0'),
m('text', { onclick: () => actions.setNode(idxB, !inputB), x: '13', y: '65', 'text-anchor': 'middle', 'font-size': '12' }, 'B = ', inputB ? '1' : '0'),
m('text', { x: '86', y: '40', 'text-anchor': 'middle', 'font-size': '12' }, 'Q = ', output ? '1' : '0'),
// sign in gate
m('text', {x: '45', y: '40', 'text-anchor': 'right', 'font-size': '18'}, "≥1")
]
),
);
}
};
Short explanation
There is an array of values (initially: false values) called nodes. Nodes are used as fictive nodes in real logical circuit. Every gate has two inputs ("connected" to nodes) and one output ("connected" to node). All nodes are in one array; index is used to work with specific node (item of array). Indexes of nodes for inputs and output are put to the component via attributes.
m(ORGate, { state: nodeState, actions: nodeActions, idxA: idxA, idxB: idxB, idxQ: 2 }),
Source code
Complete source code with visualization is on flems playground.
Hope this is useful for you, developers. A little note: chatGPT AI did most of the work.
Top comments (0)