История использования не определена в пользовательском перехватчике react

#javascript #reactjs #react-hooks

#javascript #reactjs #реагирующие перехваты

Вопрос:

Я хочу, чтобы голосовой помощник AI Alan AI был интегрирован в мое приложение react
, поэтому в основном хочу перенаправлять страницы с помощью голосовой команды.

Но проблема в том, что я хочу использовать метод push-метода хука useHistory для изменения страниц, но всякий раз, когда я обращаюсь к переменной, она не определена, я не хочу использовать window.location.href , поскольку она каждый раз обновляет приложение,

Может кто-нибудь подсказать мне, где я ошибаюсь, используя этот хук / или любые другие альтернативы

 import { useCallback, useEffect, useState } from "react";
import { useHistory } from "react-router-dom";

import { useCartContext } from "../context/cart_context";
import { useThemeContext } from "../context/theme_context";

import alanBtn from "@alan-ai/alan-sdk-web";

const COMMANDS = {
  OPEN_CART: "open-cart",
  TOGGLE_THEME: "toggle-theme",
};

const useAlan = () => {
  let history = useHistory();
  const { theme, toggleTheme } = useThemeContext();
  const { cart } = useCartContext();

  const [alanInstance, setAlanInstance] = useState(null);

  const openCart = useCallback(() => {
    if (cart.length < 1) {
      alanInstance.playText("cart is empty");
      return;
    }
    alanInstance.playText("opening cart");

    history.push("/cart");
    // window.location.href = "/cart";
  }, [alanInstance]);

  const changeTheme = useCallback(() => {
    alanInstance.playText("changing theme");
    toggleTheme();
  });

  useEffect(() => {
    window.addEventListener(COMMANDS.OPEN_CART, openCart);
    window.addEventListener(COMMANDS.TOGGLE_THEME, changeTheme);
    return () => {
      window.removeEventListener(COMMANDS.OPEN_CART, openCart);
      window.removeEventListener(COMMANDS.TOGGLE_THEME, changeTheme);
    };
  }, [openCart, changeTheme]);

  useEffect(() => {
    // history.push("/cart");
    // this also gives same error

    if (alanInstance != null) return;
    setAlanInstance(
      alanBtn({
        key: process.env.REACT_APP_ALAN_KEY,
        onCommand: ({ command }) => {
          window.dispatchEvent(new CustomEvent(command));
        },
      })
    );
  }, []);
  return null;
};

export default useAlan;

 

Все работает нормально, голос обнаружен и запущена функция OpenCart,
просто это history не определено

Ошибка:

 TypeError: Cannot read property 'push' of undefined
(anonymous function)
C:/Users/Sachin Verma/Desktop/Web Dev/React-E-Commerce-v2/src/hooks/useAlan.js:28
  25 |    }
  26 |    alanInstance.playText("opening cart");
  27 | 
> 28 |    history.push("/cart");
     | ^  29 |    // window.location.href = "/cart";
  30 |  }, [alanInstance]);
  31 | 
 

App.js код:

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

import { useThemeContext } from "./context/theme_context";
import useAlan from "./hooks/useAlan";

import { Navbar, Sidebar, Footer } from "./components";
import {
  Home,
  SingleProduct,
  Cart,
  Checkout,
  Error,
  About,
  Products,
  PrivateRoute,
  AuthWrapper,
  Scan,
  History,
  ItemList,
} from "./pages";

function App() {
  const { theme } = useThemeContext();

  useAlan();

  useEffect(() => {
    if (theme === "dark-theme") {
      // set dark mode theme
      document.documentElement.className = "dark-theme";
    } else {
      // remove dark mode
      document.documentElement.className = "light-theme";
    }
  }, [theme]);

  return (
    <AuthWrapper>
      <Router>
        <Navbar />
        <Sidebar />

        <Switch>
          <Route exact path="/">
            <Home />
          </Route>

          <Route exact path="/about">
            <About />
          </Route>

          <Route exact path="/cart">
            <Cart />
          </Route>

          <Route exact path="/products">
            <Products />
          </Route>

          <PrivateRoute exact path="/history">
            <History />
          </PrivateRoute>

          <PrivateRoute exact path="/scan">
            <Scan />
            <ItemList />
          </PrivateRoute>

          <Route exact path="/products/:id" children={<SingleProduct />} />

          <PrivateRoute exact path="/checkout">
            <Checkout />
          </PrivateRoute>

          <Route path="*">
            <Error />
          </Route>
        </Switch>
        <Footer />
      </Router>
    </AuthWrapper>
  );
}

export default App;
 

Комментарии:

1. Этот хук используется, если ваше приложение использует маршрутизацию с этим маршрутизатором. Вы используете его или просто здесь для навигации?

2. Также может быть, что значение history не имеет правильного значения при использовании useCallback . Попробуйте также добавить history к зависимостям этого массива useCallback

3. У меня была такая же проблема, дело в том, что в альфа-версии useHistory удалена

4. Правильно ли ваш код приложения помещен в a <BrowserRouter> ?

Ответ №1:

Это происходит, когда вы неправильно вкладываете свое приложение в допустимый Router , который предоставляет контекст для history объекта. Убедитесь, что ваш код верхнего уровня помещен в надлежащий Router контекст объекта:

 import { BrowserRouter } from "react-router-dom";

function App() {
    return (
        <BrowserRouter>
            ...(components that use react-router-hooks)
        </BrowserRouter>
    );
}
 

То же самое относится и к React-Native: NativeRouter .

Комментарии:

1. да, я завернул все в browserrouter в app.js

2. @sachuverma Используется ли этот пользовательский перехват вне области действия маршрутизатора? Например, в AuthWrapper самом?

3. Я так не думаю… Но вы можете увидеть весь мой код github.com/sachuverma/React-E-Commerce-v2

4. @sachuverma Что значит «я так не думаю»? Вы используете его в первой строке App.js тела: github.com/sachuverma/React-E-Commerce-v2/blob/master/src /… — строка 26. Ответ, который я вам дал, абсолютно верен. Оберните свой App компонент в Router in index.js .

5. хорошо, хорошо, я понял, я думал, что вызываю функцию в App.js и я обернул его вокруг маршрутизатора, но это были компоненты внутри App.js не весь App.js обернут вокруг маршрутизатора …. спасибо за помощь

Ответ №2:

useHistory изменилась в версии 6, useHistory теперь useNavigate, и мы можем использовать ее следующим образом:

вместо:

 const history = useHistory()
history.push('/')
 

теперь мы используем:

 const navigate = useNavigate()
naviaget('/')
 

Комментарии:

1. Большое вам спасибо, я искал, но не смог найти правильного решения большинство решений были устаревшими с предыдущими версиями react-router-dom, кстати, я использую эти версии «react»: «17.0.2», «react-dom»: «17.0.2», «react-router-dom»: «6.2.1»

Ответ №3:

Если вы работаете в App.js , вам нужно будет переместить свой

 <Router> </Router> 
 

там для вашего index.js

и оберните его так:

  <Router>
    <App />
 </Router>
 

и это должно работать как шарм.