Skip to content

Instantly share code, notes, and snippets.

@sakilahmmad71
Created March 3, 2022 07:25
Show Gist options
  • Select an option

  • Save sakilahmmad71/6b99e405f6a468a00bed889f9f751a49 to your computer and use it in GitHub Desktop.

Select an option

Save sakilahmmad71/6b99e405f6a468a00bed889f9f751a49 to your computer and use it in GitHub Desktop.
const actionTypes = {
toggle: 'TOGGLE',
on: 'ON',
off: 'OFF',
}
function toggleReducer(state, action) {
switch (action.type) {
case actionTypes.toggle: {
return {on: !state.on}
}
case actionTypes.on: {
return {on: true}
}
case actionTypes.off: {
return {on: false}
}
default: {
throw new Error(`Unhandled type: ${action.type}`)
}
}
}
function useToggle({reducer = toggleReducer} = {}) {
const [{on}, dispatch] = React.useReducer(reducer, {on: false})
const toggle = () => dispatch({type: actionTypes.toggle})
const setOn = () => dispatch({type: actionTypes.on})
const setOff = () => dispatch({type: actionTypes.off})
return {on, toggle, setOn, setOff}
}
// export {useToggle, actionTypes, toggleReducer}
function Toggle() {
const [clicksSinceReset, setClicksSinceReset] = React.useState(0)
const tooManyClicks = clicksSinceReset >= 4
const {on, toggle, setOn, setOff} = useToggle({
reducer(currentState, action) {
const changes = toggleReducer(currentState, action)
if (tooManyClicks && action.type === actionTypes.toggle) {
// other changes are fine, but on needs to be unchanged
return {...changes, on: currentState.on}
} else {
// the changes are fine
return changes
}
},
})
return (
<div>
<button onClick={setOff}>Switch Off</button>
<button onClick={setOn}>Switch On</button>
<Switch
onClick={() => {
toggle()
setClicksSinceReset(count => count + 1)
}}
on={on}
/>
{tooManyClicks ? (
<button onClick={() => setClicksSinceReset(0)}>Reset</button>
) : null}
</div>
)
}
function App() {
return <Toggle />
}
ReactDOM.render(<App />, document.getElementById('root'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment