I have a question "Make a “room” with a light that has 4 levels – off, low, medium, high – and change the level each time you press a button. Create a second button to turn the lights off." I'm assuming that I need to manage three levels i.e. low, medium, high by pressing a single button like we toggle states and have to use another button for turning the light off. But my knowledge is limited to managing each switch case of a reducer on a separate button.
Asked
Active
Viewed 740 times
-1
-
Do you really need to use ```useReducer``` ? – Lafi Oct 11 '20 at 13:25
-
yes actually it's an exercise question from a book "Pure React ". – Rija Shaheed Oct 11 '20 at 17:31
-
I'll provide you both solutions .. – Lafi Oct 11 '20 at 17:57
1 Answers
0
So here is a solution with and without useReducer, but first lets set the states config in a new helper file stateHelper.js
:
export const states = {
off: {
value: "off",
next: "low",
},
low: {
value: "low",
next: "medium",
},
medium: {
value: "medium",
next: "hight",
},
hight: {
value: "hight",
next: "low",
},
};
export const opacities = {
off: 1,
low: 0.3,
medium: 0.7,
hight: 1,
};
Solution without useReducer
:
import React, { useCallback, useState } from 'react';
import { states, opacities } from './statesHelper';
function AppWithoutUseReducer() {
const [currentState, setState] = useState(states.off);
const handleToggle = useCallback(
() => setState(states[currentState.next]),
[currentState.next]
);
const handleSetOff = useCallback(
() => setState(states[states.off.value]),
[]
);
return (
<div
style={{
margin: '50px',
border: '1px solid',
}}
>
<center style={{ opacity: opacities[currentState.value] }}>
<h1>{currentState.value}</h1>
</center>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<button onClick={handleToggle}>toggle</button>
<button onClick={handleSetOff}>off</button>
</div>
</div>
);
}
Solution with useReducer
:
import React, { useCallback, useReducer } from 'react';
import { states, opacities } from './statesHelper';
// const appReducer = (state, action) => {
// switch (action.type) {
// case states.off.value:
// return states.off;
// case states.low.value:
// return states.low;
// case states.medium.value:
// return states.medium;
// case states.hight.value:
// return states.hight;
// default:
// return state;
// }
// };
// appReducer is refactored to appReducerGeneric
const appReducerGeneric = (state, action) => {
if (states[action.type]) {
return states[action.type];
}
return state;
}; // it's like we don't need a useReducer ??
function AppUsingUseReducer() {
const [currentState, dispatch] = useReducer(appReducerGeneric, states.off);
const handleToggle = useCallback(
() => dispatch({ type: currentState.next }),
[currentState.next]
);
const handleSetOff = useCallback(
() => dispatch({ type: states.off.value }),
[]
);
return (
<div
style={{
margin: '50px',
border: '1px solid',
}}
>
<center style={{ opacity: opacities[currentState.value] }}>
<h1>{currentState.value}</h1>
</center>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<button onClick={handleToggle}>toggle</button>
<button onClick={handleSetOff}>off</button>
</div>
</div>
);
}
export default AppUsingUseReducer;
This is a codesandbox demo.

Lafi
- 1,310
- 1
- 15
- 14