#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
inindex.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>
и это должно работать как шарм.