Getting and error called Invalid Hook call in react - javascript

import { useState } from 'react';
import "./Searchbar.css"
import SearchIcon from '#material-ui/icons/Search';
import MicIcon from '#material-ui/icons/Mic';
import { Button } from '#material-ui/core';
import { useHistory } from "react-router-dom";
function Searchbar() {
const history = useHistory();
const[input, setInput] = useState('');
const search = (e) =>{
e.preventDefault();
// when the click enter button
history.push("/search")
}
return (
<form className="search">
<div className="search_box">
<SearchIcon className="search_icon" />
<input value={input} onChange={e => setInput(e.target.value)}></input>
<MicIcon />
</div>
<div className="search_cards">
<Button type='submit' onClick={search} variant="outlined">Google Search</Button>
<Button variant="outlined">I'm Feeling Lucky</Button>
</div>
</form>
)
}
export default Searchbar;
"dependencies": {
"#material-ui/core": "^4.12.3",
"#material-ui/icons": "^4.11.2",
"#testing-library/jest-dom": "^5.14.1",
"#testing-library/react": "^11.2.7",
"#testing-library/user-event": "^12.8.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.3.0",
"react-scripts": "4.0.3",
"web-vitals": "^1.1.2"
},
this is the my code. i have tried to use **useHistory** hook to redirect to the searchpage when i have clicked that search button.
but after adding Use History hook it displays message like
Invalid hook call. Hooks can only be called inside of the body of a function component.
is it wrong that the way i have called **useHistory** hook???
Github repo

Related

React Router is Not working when using octa-react

I am using octa-react library for authentication here. I have also given the dependencies below. I'm trying to pass my config data to octa login page if its authenticated then redirect to admin page in the project. In terminal its not showing any error but when I run this code its showing me this error. I'm stuck with this from last three days.
No routes matched location "/"
App.js
import React,{ PureComponent } from "react";
import axios from "axios";
import { BrowserRouter as Router, Route, Routes, useNavigate } from "react-router-dom";
import { OktaAuth, toRelativeUrl } from '#okta/okta-auth-js';
import { Security, LoginCallback, SecureRoute } from "#okta/okta-react";
import { createStore } from "redux";
import { Provider } from "react-redux";
import { createBrowserHistory } from "history";
import Home from "./Home";
import { allReducers } from "./redux/reducers";
import Loader from "./views/Common/Loader";
const browserHistory = createBrowserHistory();
const oktaauth = new OktaAuth(config.oidc);
const store = createStore(
allReducers,
{},
window.devToolsExtension && window.devToolsExtension()
);
const HasAccessToRouter = ({ data }) => {
const history = useNavigate();
const restoreoriginalUri = async (_oktaAuth, originalUri) => {
history.replace(toRelativeUrl(originalUri || '/', window.location.origin));
};
return (
<Security {...data.oidc} oktaAuth={oktaauth} restoreOriginalUri={restoreoriginalUri} >
<SecureRoute path="/" exact element={ <Home data={data} />}/>
<Routes>
<Route exact path="/implicit/callback" element={LoginCallback} />
</Routes>
</Security>
);
};
class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
isLoading: true,
response: {},
};
}
componentDidMount() {
this.getSettingsFromFile();
}
getSettingsFromFile = async () => {
try {
const response = await axios.get(
`${
process.env.PUBLIC_URL
? process.env.PUBLIC_URL
: `${window.location.origin}`
}/settings.json`
);
localStorage.setItem("apiUrl", response.data.API_URL || "");
this.setState({
isLoading: false,
response: response.data,
//dashboardtype:""
});
} catch (error) {
this.setState({
isLoading: false,
response: {},
});
}
};
render() {
const { response, isLoading } = this.state;
if (isLoading) {
return <Loader />;
}
return (
<div>
<Provider store={store}>
<Router
history={browserHistory}
basename={process.env.PUBLIC_URL || "/admini"}>
<Routes>
<Route element={ <HasAccessToRouter data={response} /> } />
</Routes>
</Router>
</Provider>
</div>
);
}
}
export default App;
Home.js
import { useOktaAuth } from "#okta/okta-react";
import React, { useEffect, useState } from "react";
import DefaultLayout from "./containers/DefaultLayout/DefaultLayout";
// import Login from "./Login";
import { Spin, Button } from "antd";
import { isEmpty } from "lodash";
const Home = (props) => {
const { authState, oktaAuth } = useOktaAuth();
const [userInfo, setUserInfo] = useState(null);
useEffect(() => {
if (!authState.isAuthenticated) {
// When user isn't authenticated, forget any user info
setUserInfo(null);
} else {
oktaAuth.getUser().then((info) => {
setUserInfo(info);
});
}
}, [authState, oktaAuth ]); // Update if authState changes
// redirect to okta login
const login = async () => {
oktaAuth.signInWithRedirect();
};
return (
<div>
{authState.isAuthenticated !== null && (
<div>
{authState.isAuthenticated && !isEmpty(userInfo) ? (
<div>
<DefaultLayout {...props} />
</div>
) : (
<div className="spinner">
<Spin tip="Loading..." />
</div>
)}
{!authState.isAuthenticated && (
<div>
<p>Please login to access the portal.</p>
<Button id="login-button" type={"primary"} onClick={login}>
Login
</Button>
</div>
)}
</div>
)}
</div>
);
};
export default Home;
package.json
"dependencies": {
"#ant-design/icons": "^4.7.0",
"#coreui/coreui": "^4.2.0",
"#coreui/coreui-plugin-chartjs-custom-tooltips": "^1.3.1",
"#coreui/icons": "2.1.0",
"#coreui/react": "^4.3.0",
"#okta/okta-auth-js": "^6.7.6",
"#okta/okta-react": "^6.5.0",
"#okta/okta-signin-widget": "^6.5.0",
"antd": "^4.21.7",
"antd-password-input-strength": "^2.0.1",
"axios": "^0.27.2",
"bootstrap": "^5.2.0",
"classnames": "^2.3.1",
"core-js": "^3.23.5",
"cross-env": "7.0.3",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",
"flag-icon-css": "^3.3.0",
"font-awesome": "^4.7.0",
"history": "^5.3.0",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"moment-timezone": "^0.5.34",
"node-sass": "^7.0.1",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-app-polyfill": "^3.0.0",
"react-chartjs-2": "^4.3.1",
"react-datalist": "^4.0.0",
"react-datalist-field": "^20.3.1",
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
"react-hot-loader": "^4.13.0",
"react-idle-timer": "^5.4.1",
"react-loadable": "^5.5.0",
"react-redux": "^8.0.2",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"react-spinners": "^0.13.3",
"react-test-renderer": "^18.2.0",
"reactstrap": "^9.1.2",
"redux": "^4.2.0",
"redux-thunk": "^2.4.1",
"simple-line-icons": "^2.5.5"
}

How to navigate through routing on button click in react. react-router": "^6.2.1 [duplicate]

This question already has answers here:
React navigate router v6 invalid hook call
(5 answers)
Problem in redirecting programmatically to a route in react router v6
(1 answer)
Closed 11 months ago.
How to navigate through routing on button click in react.
I am trying to acess some other class using routing ( "react-router": "^6.2.1",) in reactJS. When I am clicking I am getting this error.
Cannot read properties of undefined (reading 'push')
Here is my class
import React, { Component } from "react";
import { withRouter } from 'react-router-dom';
import { useHistory } from "react-router-dom";
import Button from "#mui/material/Button";
class MyBar extends Component {
constructor(props) {
super(props);
this.state = {};
this.createNew = this.createNew.bind(this);
}
createNew () {
this.props.history.push('/new');
}
render() {
return (
<div>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<div class="d-grid gap-2 col-2 mx-auto">
<button type="create" class="btn btn-outline-primary" onClick={this.createNew}> Create Post </button>
</div>
</div>
</nav>
</div>
);
}
}
export default MyBar;
Here is my dependency
"dependencies": {
"#emotion/react": "^11.8.1",
"#emotion/styled": "^11.8.1",
"#mui/material": "^5.4.3",
"#testing-library/jest-dom": "^5.16.2",
"#testing-library/react": "^12.1.3",
"#testing-library/user-event": "^13.5.0",
"axios": "^0.26.0",
"bootstrap": "^5.1.3",
"draft-js": "^0.11.7",
"font-awesome": "^4.7.0",
"react": "^17.0.2",
"react-bootstrap": "^2.1.2",
"react-dom": "^17.0.2",
"react-draft-wysiwyg": "^1.14.7",
"react-icons": "^4.3.1",
"react-pro-sidebar": "^0.7.1",
"react-router": "^6.2.1",
"react-router-dom": "^6.2.1",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.4"
},
But in other version( "react-router-dom": "^5.2.0",) of app by using this in the export
export default withRouter(ListOfEmployee);
I was easily able to navigate.
Can anybody help me here.
PS: I know there are multiple answer but none of them are its working and not getting much from the git and offcial docs.
In v6 you can use useNavigate:
const navigate = useNavigate()
navigate('/new')
It should work
class Login extends Component {
nextPath(path) {
this.props.history.push(path);
}
render() {
return (
<div>
<button type='button' onClick={() => this.nextPath('/yourpath') } >Button</button>
</div>
);
}

react-native-elements fontFamily issue

After installing react-native-elements and its dependencies, I'm unable to get the SearchBar component to render as it should
import React, { useState } from 'react';
import { View, StyleSheet } from 'react-native';
import { Ionicons, MaterialIcons } from '#expo/vector-icons';
import { SearchBar } from 'react-native-elements';
const HomeScreen = () => {
const [search, setSearch] = useState('');
return (
<View>
<SearchBar
placeholder="Search, organisations, projects, and more"
value={search}
onChangeText={(searchTerm) => setSearch(searchTerm)}
/>
</View>
);
};
In the terminal console I get the following warnings
fontFamily "Material Icons" is not a system font and has not been loaded through Font.loadAsync.
- If you intended to use a system font, make sure you typed the name correctly and that it is supported by your device operating system.
- If this is a custom font, be sure to load it with Font.loadAsync.
at node_modules/expo-font/build/Font.js:27:16 in processFontFamily
at src/context/index.js:29:19 in loginUser
Here is my package.json dependencies
"dependencies": {
"#expo/vector-icons": "^12.0.5",
"#react-navigation/bottom-tabs": "^6.0.9",
"#react-navigation/drawer": "^6.1.8",
"#react-navigation/native": "^6.0.6",
"#react-navigation/stack": "^6.0.11",
"axios": "^0.24.0",
"expo": "~44.0.0",
"expo-camera": "~12.1.0",
"expo-image-picker": "^12.0.1",
"expo-status-bar": "~1.2.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-44.0.0.tar.gz",
"react-native-elements": "^3.4.2",
"react-native-gesture-handler": "~2.1.0",
"react-native-pager-view": "^5.4.9",
"react-native-reanimated": "~2.3.1",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "^3.10.1",
"react-native-vector-icons": "^9.0.0",
"react-native-web": "~0.17.5"
},
"devDependencies": {
"#babel/core": "^7.16.5",
"#babel/preset-typescript": "^7.16.7"
},
All the resource on the matter I've found so far are a couple of years old and don't solve my problem, for example:
fontFamily Material Icons is not a system font and has to be Loaded through Exponent
and
console.error : "fontFamily "Material Icons" is not a system font and has not been loaded through Font.loadAsync
The icons need to be preloaded at the start of the App.
Reference here
This is what I had to do in App.js:
import { useFonts } from 'expo-font';
import AppLoading from 'expo-app-loading';
export default () => {
const [fontsLoaded] = useFonts({
Ionicons: require('#expo/vector-icons/build/vendor/react-native-vector-icons/Fonts/Ionicons.ttf'),
MaterialIcons: require('#expo/vector-icons/build/vendor/react-native-vector-icons/Fonts/MaterialIcons.ttf'),
'Material Icons': require('#expo/vector-icons/build/vendor/react-native-vector-icons/Fonts/MaterialIcons.ttf'),
});
if (!fontsLoaded) {
return <AppLoading />;
}
return (
<Main />
);
};

Style import (with webpack) on react js

I'm working on a React project and I'm trying to use this library(https://www.npmjs.com/package/react-image-gallery)
from npm And from the Documentation, they say we must add these instructions to import the CSS
my component
import React from 'react'
import "~react-image-gallery/styles/css/image-gallery.css";
import "~react-image-gallery/styles/scss/image-gallery.scss";
import ImageGallery from 'react-image-gallery';
export function Features() {
const images = [
{
original: 'https://picsum.photos/id/1018/1000/600/',
thumbnail: 'https://picsum.photos/id/1018/250/150/',
},
{
original: 'https://picsum.photos/id/1015/1000/600/',
thumbnail: 'https://picsum.photos/id/1015/250/150/',
},
{
original: 'https://picsum.photos/id/1019/1000/600/',
thumbnail: 'https://picsum.photos/id/1019/250/150/',
},
];
return (
<div>
<ImageGallery items={images} />;
</div>
)
}
my packeg json
"dependencies": {
"#material-ui/core": "^4.12.3",
"#material-ui/icons": "^4.11.2",
"#mui/icons-material": "^5.2.4",
"#mui/material": "^5.2.4",
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.1.0",
"#testing-library/user-event": "^12.1.10",
"axios": "^0.24.0",
"bootstrap": "^5.1.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-image-gallery": "^1.2.7",
"react-material-ui-carousel": "^3.1.1",
"react-redux": "^7.2.6",
"react-router-dom": "^6.0.2",
"react-scripts": "4.0.3",
"redux-thunk": "^2.4.1",
"styled-components": "^5.3.3",
"web-vitals": "^1.0.1"
},
But when I add this in my Component it gives me this ERROR
If there is no solution, please suggest to me the name of a library similar to this
Thanks everyone, the issue is resolved
I added this to the component
import "react-image-gallery/styles/css/image-gallery.css";
import React from 'react'
import "react-image-gallery/styles/css/image-gallery.css";
import ImageGallery from 'react-image-gallery';
import {ImgGallery} from "./Styled.js"
export function ShopDetails() {
const images = [
{
original: 'https://picsum.photos/id/1018/1000/600/',
thumbnail: 'https://picsum.photos/id/1018/250/150/',
},
{
original: 'https://picsum.photos/id/1015/1000/600/',
thumbnail: 'https://picsum.photos/id/1015/250/150/',
},
{
original: 'https://picsum.photos/id/1019/1000/600/',
thumbnail: 'https://picsum.photos/id/1019/250/150/',
},
];
return (
<ImgGallery>
<ImageGallery thumbnailPosition="left" useBrowserFullscreen={false}
showPlayButton={false} autoPlay={true} items={images} />;
</ImgGallery>
)
}
You must import only the components from the library, not the css or scss files.
For example import ImageGallery from 'react-image-gallery' and use it below like <ImageGallery/> as usual.
If it's not successful than try to import css/scss files to index.js

ReactJS props aren't being passed to other component when navigating?

So in my app I have a login-component and an authenticator-component. The last one works with QR code authorization etc.
Since the package "node-sass" is deprecated now, I changed to the "sass" NPM package. I had to upgrade "react-router" and "react-router-dom" as well to their latest version (6...).
Here's my dependencies:
"dependencies": {
"#material-ui/core": "^4.11.0",
"#material-ui/icons": "^4.9.1",
"#material-ui/lab": "^4.0.0-alpha.56",
"#react-pdf/renderer": "^1.6.12",
"#reduxjs/toolkit": "^1.4.0",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"axios": "^0.20.0",
"caniuse-lite": "^1.0.30001197",
"moment": "^2.29.1",
"qrcode.react": "^1.0.0",
"qs": "^6.9.4",
"react": "^16.13.1",
"react-async": "^10.0.1",
"react-dom": "^16.13.1",
"react-fade-in": "^1.1.0",
"react-icons": "^3.11.0",
"react-movable": "^2.5.3",
"react-outside-click-handler": "^1.3.0",
"react-qr-reader": "^2.2.1",
"react-redux": "^7.2.1",
"react-router": "^6.0.2",
"react-router-dom": "^6.0.2",
"react-scripts": "3.4.3",
"redux": "^4.0.5",
"redux-axios-middleware": "^4.0.1",
"redux-devtools-extension": "^2.13.8",
"redux-thunk": "^2.3.0",
"sass": "^1.43.4",
"xlsx": "^0.16.8"
},
So my next step was to change everything from "react-router" and "react-router-dom" to use their latest items, like "useHistory" was changed to "useNavigate" etc.
Their "history.push("/route")" was also changed to "navigate("/route")" now, so I changed those as well.
And lastly, they removed the "withRouter" function from their package, which used to be required for navigation to work inside main App. It used to be like this:
export default withRouter(App);
But now this is the hook that it replaces:
import React from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
export const withRouter = (Component) => {
const Wrapper = (props) => {
const navigate = useNavigate();
const location = useLocation();
return (
<Component
{...props}
navigate={navigate}
location={location}
/>
);
};
return Wrapper;
};
And then you import that one, and use "withRouter(App)" etc...
Here's (part of) my App Routing:
return (
<ThemeProvider theme={theme}>
<Loading />
<Header
menuHandler={() => {
changeMenu(!showMenu);
}}
setActive={setActive}
/>
<main className="main">
<MenuBar
showMenu={showMenu}
toggleMenu={() => changeMenu(!showMenu)}
active={active}
setActive={setActive}
/>
<Container className="main__container" id="main__container">
<MySnackbar />
<Modal />
<Routes>
<Route
path="/scanner"
element={
<ScannerScreen />
}
/>
<Route
path="/authenticator"
element={
<Authenticator />
}
/>
<Route
path="/login"
element={
<Login />
}
/>
...
As you can see, where it says now "Routes" is where it used to say "Switch" in previous "react-router-dom" versions.
I used to navigate between pages, like so:
import { useNavigate } from "react-router-dom";
...
const navigate = useNavigate();
...
navigate("/authenticator", {
authMode: "login",
username: user.username,
});
As you can see, I'm using the V6 "navigate" from "react-router-dom" now instead of the previous "history.push('/authenticator')" for example.
This navigation works, however no props are passed (like authMode & username) and the props are always "undefined" in the target/new component, when here/source component they are filled in.
No matter what I do, props are always undefined, like so:
// both authMode & username will be undefined
const Authenticator = ({ authMode, username }) => {...}
// props will be undefined
const Authenticator = (props) => {...}
// both of these will return undefined values
const Authenticator = () => {
const { authMode, username } = useParams();
const { authMode, username } = useLocation();
}
Does anyone have any idea how I can properly pass props from Login to my Authenticator, using Javascript, like so:
navigate("/authenticator", {
authMode: "login",
username: user.username,
});
Thanks!
So, of course, right after posting a stackoverflow post I kept on digging and finally found "a" solution myself. I'm not sure if this is the best way, but here it is.
Looking at this post: https://stackoverflow.com/a/64566486/3384458 , props are no longer "just" passed to other components. It has to go via the "location" prop now.
So now I have to do it like this, in my Login-component:
navigate("/authenticator", {
state: {
authMode: "login",
username: user.username,
}
});
You have to set the "location.state" prop of "location", like above.
Now the "location.state" prop will contain my object with "authMode" and "userName".
In my Authenticator-component, I do it like this now:
const { authMode, username } = useLocation().state;
Here's another helpful link for react-router v6: https://remix.run/blog/react-router-v6

Categories