在 React 中使用 TypeScript 的 useReducer Hook

2025-06-04

在 React 中使用 TypeScript 的 useReducer Hook

useReducer钩子是useState钩子的替代品,当你有复杂的状态逻辑或者当你的下一个状态依赖于你之前的状态时,它是更可取的。

useReducer 钩子接受一个 reducer 类型(state, action) => newState并返回一个与调度方法配对的状态对象,就像 Redux 一样。

现在,官方useReducer 文档将向您展示如何定义一个接受您将使用调度方法调用的操作的 reducer。

这是一个很好的用例,但我还有另一个用于useReducer提供状态部分更新的例子,我发现它涵盖了我的其余用例。

带有操作和调度方法的 useReducer

默认示例useReducer已设置,用于创建一个 Reducer 函数并为其提供一个 Action。该 Action 应包含一个类型以及用于更新状态的值。

为了使用 TypeScript 强类型化此功能,我们可以创建一个包含所有可能的操作类型的枚举,并为该操作创建一个接口。

下面是一个相当设计的例子,但展示了最基本的例子。

// An enum with all the types of actions to use in our reducer
enum CountActionKind {
  INCREASE = 'INCREASE',
  DECREASE = 'DECREASE',
}

// An interface for our actions
interface CountAction {
  type: CountActionKind;
  payload: number;
}

// An interface for our state
interface CountState {
  count: number;
}

// Our reducer function that uses a switch statement to handle our actions
function counterReducer(state: CountState, action: CountAction) {
  const { type, payload } = action;
  switch (type) {
    case CountActionKind.INCREASE:
      return {
        ...state,
        value: state.count + payload,
      };
    case CountActionKind.DECREASE:
      return {
        ...state,
        value: state.count - payload,
      };
    default:
      return state;
  }
}

// An example of using the `useReducer` hooks with our reducer function and an initial state
const Counter: FunctionComponent = () => {
  const [state, dispatch] = useReducer(counterReducer, { count: 0 });
  return (
    <div>
      Count: {state.count}
      {/* Calling our actions on button click */}
      <button
        onClick={() => dispatch({ type: CountActionKind.INCREASE, payload: 5 })}
      >
        -
      </button>
      <button onClick={() => dispatch({ type: CountActionKind.DECREASE, payload: 5 })}>+</button>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

useReducer 使用 Partial 类型进行状态更新

useReducer当您有一个状态对象并且需要直接更改其中的某些值而不是分派动作来处理状态变化时,最好使用下一种使用方式。

这种方式的类型也较少,但确实暴露了要直接改变的状态,因此在使用此方法时要考虑到这一点。

// Interface for our state
interface LoadingState {
  loaded: boolean;
  loading: boolean;
  error: Error | null;
}

// The example component that use the `useReducer` hook with our state
const LoadingComponent: FunctionComponent = () => {
  /** 
   See here that we are using `newState: Partial<LoadingState>` in our reducer
   so we can provide only the properties that are updated on our state
   */
  const [state, setState] = useReducer(
    (state: LoadingState, newState: Partial<LoadingState>) => ({
      ...state,
      ...newState,
    }),
    {
      loaded: false,
      loading: false,
      error: null,
    }
  );

  useEffect(() => {
    // And here we provide only properties that are updating on the state
    setState({ loading: true });
    setState({ loading: false, loaded: true });
    setState({ loading: false, loaded: true, error: new Error() });
  }, []);

  if (state.loading) {
    return <p>Loading</p>;
  }

  return <p>{state}</p>;
};
Enter fullscreen mode Exit fullscreen mode

结论

以上是我的两种方法,请查看下面的其他帖子,了解其他方法。了解实现同一件事的各种方法,会很有帮助。

https://www.newline.co/@bespoyasov/how-to-use-usereducer-with-typescript--3918a332

https://www.sumologic.com/blog/react-hook-typescript/

https://www.benmvp.com/blog/type-checking-react-usereducer-typescript/

🌟🌟🌟

我和我的兄弟一直在写有关 React、TypeScript、R、数据科学的文章,您可以在我们的博客上找到所有内容,请查看:

KoalaTea.io

🌟🌟🌟

文章来源:https://dev.to/craigaholliday/using-the-usereducer-hook-in-react-with-typescript-27m1
PREV
在 Deno 中编写 React SSR 应用程序 安装 入门 运行我们的 React SSR 应用程序 后续步骤
NEXT
Go 中环境变量的实用指南