是否可以在单个按钮上的 useReducer 钩子的 reducer 功能中管理不同的 switch case?

Is it possible to manage different switch cases in reducer function of useReducer hook on a single button?

我有一个问题“制作一个“房间”,其中的灯有 4 个级别——关闭、低、中、高——并更改级别 每次按下按钮。创建第二个按钮来关闭灯。" 我假设我需要通过按下一个按钮来管理三个级别,即低、中、高,就像我们切换状态一样,并且必须使用另一个按钮来关闭灯。但我的知识仅限于在单独的按钮上管理减速器的每个开关盒。

所以这里有一个使用和不使用 useReducer 的解决方案,但首先让我们在一个新的帮助文件中设置状态配置 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,
};

没有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>
    );
}

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;

这是一个 codesandbox 演示。