Реагировать на неверный вызов хука, даже если он соответствует всем правилам реагирования на хуки

Я делаю проект React/Typescript, и он выдает мне эту ошибку, даже если я следую всем правилам React Hooks (по крайней мере, так, как я их понял).

Ошибка: Неверный вызов ловушки. Хуки можно вызывать только внутри тела функционального компонента. Это может произойти по одной из следующих причин:

  1. У вас могут быть несоответствующие версии React и рендерера (например, React DOM).
  2. Возможно, вы нарушаете правила хуков.
  3. У вас может быть более одной копии React в одном приложении. См. https://reactjs.org/link/invalid-hook-call для получения советов по отладке и устранению этой проблемы.

Проблема в первой и второй строке компонента "Адрес"

Приложение работает нормально, за исключением случаев, когда загружается компонент Address.tsx.

Address.tsx

import React, { useState, useRef } from "react";
import { RouteComponentProps } from "react-router-dom";
import getUserAddressByCEP, { BrazilianAddress, validateCEP } from "./cep";
import { LeftContainer, FormAddress, AddressDetailsContainer } from "./checkout.styles";

interface props extends RouteComponentProps<any> {}

const Address: React.FC<props> = ({ history }) => {
    const [userAddress, setUserAddress] = useState<BrazilianAddress | null>(null);
    const inputCEP = useRef<HTMLInputElement>(null);

    const findUserAddress = async () => {
        if (!inputCEP.current) return;

        let isValidCEP = validateCEP(inputCEP.current.value);
        if (isValidCEP) setUserAddress(await getUserAddressByCEP(inputCEP.current.value));
    };

    return (
        <>...</>
    );
};

export default Address;

Основываясь на моем поиске этой проблемы в Google, я...

  • обновлен React и React Router Dom до последней версии
  • перезапустил сервер разработки
  • удалил файл и снова написал код
  • проверил правила React Hooks (https://reactjs.org/docs/hooks-rules.html< /а>)

Странно то, что у меня есть другой файл с той же структурой (код ниже), который работает хорошо.

import React, { useEffect, useState } from "react";
import { RouteComponentProps, Route, Switch } from "react-router-dom";

import { ReactComponent as DeliveryIcon } from "../../media/icons/003-delivery.svg";
import { ReactComponent as ChequeIcon } from "../../media/icons/042-cheque.svg";

import {
    CheckoutContainer,
    CheckoutHeader,
    CheckoutHeaderDot,
    OrderDetails,
    OrderProducts,
    GlobalStyle,
    ContainerEmptyCarMessage,
} from "./checkout.styles";

import CartItem from "../../components/Cart/CartItem";
import Address from "./Address";
import Payment from "./Payment";
import { useDispatch, useSelector } from "react-redux";
import { CartProduct, CartProductsState, DuxCartProductAction } from "../../redux/cartReducer";
import { convertToReal } from "../../utils";
import { scrollPageToTop } from "../../App";

interface props extends RouteComponentProps<any> {}

const Checkout: React.FC<props> = ({ history }) => {
    const checkoutProducts = useSelector<CartProductsState, CartProductsState["products"]>(
        (state: CartProductsState) => state.products,
    );

    const [orderFinished, setOrderFinished] = useState(false);

    const dispatch = useDispatch();

    const getCartProduct = (productId: number): CartProduct | null => {
        let auxProduct = null;
        checkoutProducts.forEach((product) => {
            if (product.productId === productId) auxProduct = product;
        });
        return auxProduct;
    };

    const finishOrder = () => {
        let action: DuxCartProductAction = {
            type: "@cart/CLEAR_CART",
        };
        setOrderFinished(true);
        dispatch(action);
        window.location.href = "/";
    };

    const increaseProductQuantity = (productId: number): void => {
        let productToIncrease = getCartProduct(productId);
        if (productToIncrease === null) return;

        let auxAction: DuxCartProductAction = {
            type: "@cart/INCREASE_PRODUCT_QUANTITY",
            data: productToIncrease,
        };
        dispatch(auxAction);
    };

    const decreaseProductQuantity = (productId: number): void => {
        let productToIncrease = getCartProduct(productId);
        if (productToIncrease === null) return;

        let auxAction: DuxCartProductAction = {
            type: "@cart/DECREASE_PRODUCT_QUANTITY",
            data: productToIncrease,
        };
        dispatch(auxAction);
    };

    if (history.location.pathname !== "/checkout/address" && history.location.pathname !== "/checkout/payment") {
        history.push("/error-404");
    }

    useEffect(() => {
        setTimeout(scrollPageToTop, 100);
    }, []);

    if (checkoutProducts.length === 0 && !orderFinished) {
        setTimeout(() => (window.location.href = "/"), 3500);
        return (
            <ContainerEmptyCarMessage>
                <h2>
                    Seu carrinho está vazio, adicione alguns itens antes de vir para esta página. Você será redirecionado(a) para
                    a página inicial.
                </h2>
            </ContainerEmptyCarMessage>
        );
    }

    let total_order = convertToReal.format(
        checkoutProducts.reduce((sum, product) => sum + product.price * product.quantity, 0),
    );

    return (
        <CheckoutContainer className="container" id="checkout_page_container">
            <CheckoutHeader>
                <span id="checkout__header_line"></span>
                <CheckoutHeaderDot id="checkout__header_dot_address">
                    <span>Endereço de entrega</span>
                    <div className="checkout__header_dot active_checkout_dot">
                        <DeliveryIcon />
                    </div>
                </CheckoutHeaderDot>
                <CheckoutHeaderDot id="checkout__header_dot_payment">
                    <span>Pagamento</span>
                    <div
                        className={`checkout__header_dot ${
                            history.location.pathname === "/checkout/payment" ? " active_checkout_dot" : ""
                        }`}
                    >
                        <ChequeIcon />
                    </div>
                </CheckoutHeaderDot>
            </CheckoutHeader>
            <Switch>
                <Route path="/checkout/address" render={Address} />
                <Route
                    path="/checkout/payment"
                    render={(props: RouteComponentProps) => <Payment {...props} finishOrder={finishOrder}></Payment>}
                />
            </Switch>

            <OrderDetails>
                <div id="order_details_header">
                    <span id="checkout__total_label">Total</span>
                    <span id="checkout__total_value">{total_order}</span>
                </div>
                <span className="normal_span" id="buying_message">
                    Você está comprando:
                </span>
                <OrderProducts>
                    {checkoutProducts.map((product, i) => (
                        <CartItem
                            key={i}
                            productId={product.productId}
                            name={product.name}
                            image={product.image}
                            price={product.price}
                            size={product.size}
                            color={product.color}
                            quantity={product.quantity}
                            increaseProductQuantity={increaseProductQuantity}
                            decreaseProductQuantity={decreaseProductQuantity}
                        />
                    ))}
                </OrderProducts>
            </OrderDetails>
            <GlobalStyle />
        </CheckoutContainer>
    );
};

export default Checkout;


person Thiago Buarque    schedule 06.07.2021    source источник
comment
Где используется Address?   -  person CertainPerformance    schedule 06.07.2021
comment
Думаю, это не имеет значения. Если я удаляю useState или useRef, все работает нормально. Но если это имеет значение, я могу отредактировать вопрос. Что вы думаете?   -  person Thiago Buarque    schedule 06.07.2021
comment
Я думаю, что это проблема, но я не уверен - вы можете отредактировать, чтобы показать, где это называется?   -  person CertainPerformance    schedule 06.07.2021
comment
Хорошо, дай мне секунду   -  person Thiago Buarque    schedule 06.07.2021
comment
Если вы вызываете Address() вместо <Address />, он все равно будет отображать JSX, но не будет считаться компонентом, а просто функцией, возвращающей элементы, что противоречит правилам хуков.   -  person Emile Bergeron    schedule 06.07.2021
comment
Я нет, я отображаю адрес с помощью React Router   -  person Thiago Buarque    schedule 06.07.2021
comment
Это должно быть component={Address} вместо render={Address}, о чем и говорит мой предыдущий комментарий.   -  person Emile Bergeron    schedule 06.07.2021
comment
Омг, спасибо!!!!!   -  person Thiago Buarque    schedule 06.07.2021