React
by Abdul Ahmad
HTML
<div id="app"></div>
CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.done {
color: rgba(0, 0, 0, 0.3);
text-decoration: line-through;
}
input {
margin-right: 5px;
}
React
const store = {
inited: false,
listeners: {},
listenerNum: 0,
data: {
count: 1,
},
};
function useState() {
const [state, setState] = React.useState(store.data);
let num;
React.useEffect(() => {
store.listenerNum += 1;
num = store.listenerNum;
store.listeners[num] = {
num,
setState,
};
() => delete store.listeners[num];
}, []);
function incrementCount() {
const newState = {
...state,
count: state.count + 1,
};
update({ newState });
}
function setStateInternal({ data } = {}) {
const newState = {
...state,
...data,
};
update({ newState });
}
function update({ newState } = {}) {
store.data = newState;
Object.values(store.listeners).forEach(i => i.setState(newState));
}
return {
incrementCount,
data: state,
setState: setStateInternal,
};
}
function App() {
const { incrementCount, data, setState } = useState();
const [inputVal, setInputVal] = React.useState('');
return (
<div>
<button onClick={incrementCount}>
updateState
</button>
<div>
<input
value={inputVal}
onChange={e => setInputVal(+e.target.value)}
/>
<button onClick={() => {
setState({ data: { count: inputVal }});
setInputVal('');
}}>
set count
</button>
</div>
<div>
app: { data.count }
</div>
<One />
<Two />
</div>
);
}
function Two() {
const { data } = useState();
return (
<div>
two: { data.count }
</div>
);
}
function One() {
const { data } = useState();
return (
<div>
one: { data.count }
</div>
);
}
ReactDOM.render(<App />, document.querySelector("#app"));