react-mx
v0.0.6
Published
Minimalism state manager
Downloads
23
Maintainers
Readme
react-mx
Counter App
import React from "react";
import { render } from "react-dom";
import mx from "react-mx";
const Count = {
value: 1
};
// computed state
const DoubleCount = {
state: Count,
value: state => state * 2
};
const Increase = {
state: Count,
dispatch: (state, step = 1) => state + step
};
const App = () => {
const [count, doubleCount, increase] = mx(Count, DoubleCount, Increase);
return (
<>
<h1>Count: {count}</h1>
<h1>Double Count: {doubleCount}</h1>
<button onClick={() => increase()}>Increase</button>
<button onClick={() => increase(2)}>Increase 2</button>
</>
);
};
render(<App />, document.getElementById("root"));
Todo App
import React, { useRef } from "react";
import { render } from "react-dom";
import mx from "react-mx";
const Todos = {
value: []
};
const AddTodo = {
// using state helper to mutate state (prop name starts with $ sign)
$state: Todos,
dispatch($todos, text) {
$todos.push({ id: Math.random().toString(36), text, done: false });
}
};
const RemoveTodo = {
$state: Todos,
dispatch($todos, id) {
$todos.filter(x => x.id !== id);
}
};
const ToggleTodo = {
$state: Todos,
dispatch($todos, id) {
$todos.map(todo => (todo.id === id ? { ...todo, done: !todo.done } : todo));
}
};
const App = () => {
const [todos, addTodo, removeTodo, toggleTodo] = mx(
Todos,
AddTodo,
RemoveTodo,
ToggleTodo
);
const inputRef = useRef();
const handleSubmit = e => {
e.preventDefault();
addTodo(inputRef.current.value);
inputRef.current.value = "";
};
return (
<>
<form onSubmit={handleSubmit}>
<input ref={inputRef} />
</form>
<ul>
{todos.map(todo => (
<li key={todo.id}>
<button onClick={() => toggleTodo(todo.id)}>Toggle</button>
<button onClick={() => removeTodo(todo.id)}>Remove</button> <span style={{ textDecoration: todo.done ? "line-through" : "none" }}>{todo.text}</span>
</li>
))}
</ul>
</>
);
};
render(<App />, document.getElementById("root"));
Greeting App
import React from "react";
import { render } from "react-dom";
import mx from "react-mx";
const FirstName = {
value: ""
};
const LastName = {
value: ""
};
const FullName = {
first: FirstName,
last: LastName,
value: ({ first, last }) => first + " " + last
};
const UpdateName = {
first: FirstName,
last: LastName,
// can update multiple states at once
dispatch(states, type, value) {
if (type === "first") {
return { first: value };
}
return { last: value };
// return { first: FirstNameValue, last: LastNameValue } to update both states
}
/**
* another dispatch version using state helper
* $first: FirstName
* $last: LastName
* dispatch({ $first, $last }, type, value) {
* if (type === 'first') {
* $first.value = value;
* }
* else if (type === 'last') {
* $last.value = value;
* }
* }
*/
};
const App = () => {
const [first, last, full, update] = mx(
FirstName,
LastName,
FullName,
UpdateName
);
return (
<>
<input
placeholder="First name"
value={first}
onChange={e => update("first", e.target.value)}
/>
<input
placeholder="Last name"
value={last}
onChange={e => update("last", e.target.value)}
/>
<h1>{full}</h1>
</>
);
};
render(<App />, document.getElementById("root"));
Using flow
import React, { useEffect } from "react";
import { render } from "react-dom";
import mx from "react-mx";
// define power states
const PowerOff = {
value: "off",
on: [["toggle", () => PowerOn]]
};
const PowerOn = {
value: "on",
on: [["toggle", () => PowerOff]]
};
// define traffic light states
const TrafficLightOff = {
value: "off",
on: [["on", () => GreenLightOn]]
};
const GreenLightOn = {
value: "green",
on: [["timer", () => YellowLightOn], ["off", () => TrafficLightOff]]
};
const YellowLightOn = {
value: "yellow",
on: [["timer", () => RedLightOn], ["off", () => TrafficLightOff]]
};
const RedLightOn = {
value: "red",
on: [["timer", () => GreenLightOn], ["off", () => TrafficLightOff]]
};
// create flows
const PowerFlow = mx.flow(PowerOff);
const TrafficLightFlow = mx
.flow(TrafficLightOff)
// should turn on/off when power state changed
.listen(PowerFlow, value => [value]);
const App = () => {
// using flow hooks
const [power, sendPowerCommand] = PowerFlow.use();
const [traffic, sendTrafficCommand] = TrafficLightFlow.use();
useEffect(() => {
const timerId = setInterval(() => {
sendTrafficCommand("timer");
}, 2000);
return () => {
clearInterval(timerId);
};
}, [sendTrafficCommand]);
return (
<>
<div
style={{
width: 100,
height: 100,
borderRadius: 100,
backgroundColor: traffic === "off" ? "gray" : traffic
}}
/>
<button
style={{ backgroundColor: power === "on" ? "green" : "red" }}
onClick={() => sendPowerCommand("toggle")}
>
{power === "on" ? "Turn power off" : "Turn power on"}
</button>
</>
);
};
render(<App />, document.getElementById("root"));