Skip to content

Instantly share code, notes, and snippets.

@abelsan
Created August 17, 2020 19:19
Show Gist options
  • Save abelsan/4b38cf85e611c87877e80eac8c01297d to your computer and use it in GitHub Desktop.
Save abelsan/4b38cf85e611c87877e80eac8c01297d to your computer and use it in GitHub Desktop.
Counters example using reducer
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Clock</title>
<!-- don't use this in production: -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<h1 style="font-family: Arial;">counters</h1>
<!-- target div -->
<div id="root"></div>
<!-- load react -->
<script
src="https://unpkg.com/react/umd/react.development.js"
crossorigin
></script>
<script
src="https://unpkg.com/react-dom/umd/react-dom.development.js"
crossorigin
></script>
<!-- react component. -->
<script src="reducer.js" defer type="text/babel"></script>
</body>
</html>
const Counter = (props) => {
const [counter, setCounter] = React.useState(Number(props.start));
// useRef to avoid the closure in the timer
const countRef = React.useRef(counter);
countRef.current = counter;
// timer
React.useEffect(() => {
const timeout = setTimeout(() => {
setCounter(counter + Number(props.increment));
props.parent({label: props.label, value: countRef.current});
}, props.interval);
// cleanup
return () => {
clearTimeout(timeout);
}
}, [counter]);
return (
<>
Child-{props.label}: {counter}
</>
);
}
function reducer(state, action) {
switch (action.type) {
case '01':
return {...state, counter01: action.value};
case '02':
return {...state, counter02: action.value};
case '03':
return {...state, counter03: action.value};
default:
throw new Error();
}
}
let initialState = {counter01: 0, counter02: 0, counter03: 0};
const Stats = () =>{
const [state, dispatch] = React.useReducer(reducer, initialState);
function parent(counter){
dispatch({type:counter.label, value: counter.value})
}
return (
<div>
<Counter
style={{padding:'25px 50px 75px 100px;'}}
label="01"
start="0"
increment="2"
interval="1000"
parent={parent} />,<br/>
Parent01: {state.counter01} <br/>
<Counter
label="02"
start="0"
increment="10"
interval="2000"
parent={parent} />,<br/>
Parent02: {state.counter02} <br/>
<Counter
label="03"
start="0"
increment="5"
interval="3000"
parent={parent} /><br/>
Parent03: {state.counter03} <br/>
</div>
)
}
ReactDOM.render(
<Stats />,
document.getElementById('root')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment