reactjs - 在使用带有钩子(Hook)的导出类时,我应该远离类吗?

标签 reactjs typescript react-redux react-hooks

这是一个基于知识的问题。我是 React 的新手,来自基于 Angular TypeScript 类的背景。我想在使用 React 时继续使用 TypeScript,但在编译 hook 时遇到问题。

此代码来自 create-react 应用程序库并使用 Redux 模板。它使用计数器组件来显示计数器。

import React, { useState } from 'react';

import { useAppSelector, useAppDispatch } from '../../app/hooks';
import {
  decrement,
  increment,
  incrementByAmount,
  incrementAsync,
  incrementIfOdd,
  selectCount,
} from './counterSlice';
import styles from './Counter.module.css';

export function Counter() {
  const count = useAppSelector(selectCount);
  const dispatch = useAppDispatch();
  const [incrementAmount, setIncrementAmount] = useState('2');

  const incrementValue = Number(incrementAmount) || 0;

  return (
    <div>
      <div className={styles.row}>
        <button
          className={styles.button}
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >
          -
        </button>
        <span className={styles.value}>{count}</span>
        <button
          className={styles.button}
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          +
        </button>
      </div>
      <div className={styles.row}>
        <input
          className={styles.textbox}
          aria-label="Set increment amount"
          value={incrementAmount}
          onChange={(e) => setIncrementAmount(e.target.value)}
        />
        <button
          className={styles.button}
          onClick={() => dispatch(incrementByAmount(incrementValue))}
        >
          Add Amount
        </button>
        <button
          className={styles.asyncButton}
          onClick={() => dispatch(incrementAsync(incrementValue))}
        >
          Add Async
        </button>
        <button
          className={styles.button}
          onClick={() => dispatch(incrementIfOdd(incrementValue))}
        >
          Add If Odd
        </button>
      </div>
    </div>
  );
}

这按预期工作,所以我将其更改为

export default class Counter extends React.Component<unknown> {
  render(): {
    const count = useAppSelector(selectCount);
    const dispatch = useAppDispatch();
    const [incrementAmount, setIncrementAmount] = useState('2');

    const incrementValue = Number(incrementAmount) || 0;

    return (
      <div>
        <div className={styles.row}>
          <button
            className={styles.button}
            aria-label="Decrement value"
            onClick={() => dispatch(decrement())}
          >
            -
          </button>
          <span className={styles.value}>{count}</span>
          <button
            className={styles.button}
            aria-label="Increment value"
            onClick={() => dispatch(increment())}
          >
            +
          </button>
        </div>
        <div className={styles.row}>
          <input
            className={styles.textbox}
            aria-label="Set increment amount"
            value={incrementAmount}
            onChange={(e) => setIncrementAmount(e.target.value)}
          />
          <button
            className={styles.button}
            onClick={() => dispatch(incrementByAmount(incrementValue))}
          >
            Add Amount
          </button>
          <button
            className={styles.asyncButton}
            onClick={() => dispatch(incrementAsync(incrementValue))}
          >
            Add Async
          </button>
          <button
            className={styles.button}
            onClick={() => dispatch(incrementIfOdd(incrementValue))}
          >
            Add If Odd
          </button>
        </div>
      </div>
    );
  }
}

但是当我编译它时 - 我得到了这个非常常见的错误

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

很明显,我的代码没有遵循任何错误(这一次,我很清楚哪个让我满意)。但这是否意味着在使用钩子(Hook)时,我现在将丢失导出默认类语法?

对于上下文,我在我的父组件 (App) 中使用了这段代码,它确实可以编译。

import React from 'react';
import './App.css';
import Counter from './features/counter/Counter';

export default class App extends React.Component<unknown> {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <Counter />
           ...

如有任何信息,我将不胜感激。谢谢

****** 编辑 *******

我看到您可以按照此处的说明使用高阶组件

How can I use React hooks in React classic `class` component?

这引出了一个问题,现在为 React 使用基于类的语法是否明智?

基于以下答案的补充阅读:https://www.twilio.com/blog/react-choose-functional-components

最佳答案

恢复到以前的状态,钩子(Hook)只能在 React Function 组件中使用。

// Correct, function component
export function Counter() {

// Incorrect, class component
export default class Counter extends React.Component<unknown> {
  render(): {

linting 问题是 #2,“打破 Hooks 规则”。具体来说,这违反了 Only Call Hooks from React Functions (您的第二个示例是 React 类而不是 React 函数)。

关于reactjs - 在使用带有钩子(Hook)的导出类时,我应该远离类吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69379800/

相关文章:

reactjs - React-datetime + 在 React 中设置时间间隔

angular - 如何在 Ionic 2 中删除 <ion-footer>

javascript - 针对剧烈变异的远程 API 进行快照测试 API 客户端

javascript - 如何正确使用 redux-observable 和 promise?

javascript - React-Redux 有多少种使用方法? Redux-thunk vs Redux-Saga?

node.js - React-Redux大型自定义数据表

reactjs - 'instanceof' 的右侧不是 React 测试库中的对象

android - 我如何在 react 原生 webview 中从网页访问当前位置

reactjs - 如何从一个页面路由到另一个页面?

Angular TypeScript 将枚举与 Spring Boot 后端结合使用