useNavigate() is not working even inside the Router context - javascript

I have a project using react-router v6, and I am getting an error stating useNavigate() may be used only in the context of a <Router> component.
For some background, I have two projects that live in the same repo and get built together. We leverage code splitting and import them as needed, not sure if this matters.
Now, I have a setup that is pretty simple:
(in the #dummyInc/components project)
Dummy.tsx
import React from 'react'
export function Dummy() {
const navigate = useNavigate()
return <div> Hello World <button onClick={() => navigate('/someRoute')}> </div>
}
Then my code uses it in a different project that is just imported.
(in the #dummyInc/site project)
App.js
import React from 'react'
import Dummy from '#dummyInc/components'
export function App() {
return <div> <Dummy /> </div>
}
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'
import App from './src/App'
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
)
Now I have the above and when I try to render it in the browser, it says the following, but I'm not sure how that's possible, it's being rendered in that context.
Error: useNavigate() may be used only in the context of a <Router> component.
Am I missing something? Any help is appreciated.

Related

I defined component and used it App.js but getting undefined error

When I try to access the relevant component under app.js, I get the error "WARNING in [eslint] rc\App.js Line 2:8: 'personAdd' is defined but never used no-unused-vars". When I run the project, I see tags in the form of in html, but the component does not appear on the screen. I have included the codes below. Thanks in advance.
Note : Changes under .eslintrc.json didn't work.
App.js
import React from 'react';
import personAdd from './screens/personAdd';
function App() {
return (
<personAdd />
)
}
export default App;
personAdd.js
import React from 'react';
class personAdd extends React.Component{
render(){
return(
<div id = "personAdd">
<h1>Kullanıcı Bilgileri</h1>
<form>
<label htmlFor="id">Ad</label>
<input id="id"/>
<button>Add</button>
</form>
</div>
)
}
}
export default personAdd;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
//import personAdd from './screens/personadd';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
/*const personadd = ReactDOM.createRoot(document.getElementById('personadd'));
personadd.render(
<React.StrictMode>
<personAdd />
</React.StrictMode>
);*/
You don't need to manually create new root elements for every component you want to render.
React inserts an initial element 'root' into the DOM so that the app can render within that.
Try removing:
/*const personadd = ReactDOM.createRoot(document.getElementById('personadd'));
personadd.render(
<React.StrictMode>
<personAdd />
</React.StrictMode>
);*/
If you want to render your personAdd component you can add it as a child of App as you've already done.
function App() {
return (
<personAdd />
)
}
The other reason you're getting these issues is because you're not using Pascal case when naming your components (PersonAdd).
function App() {
return (
<PersonAdd />
)
}
In addition as others have mentioned, stick to function components rather than class components.
I'd recommend having a look at the React Beta Docs which now do everything with functional components. There are helpful walkthroughs on there that should help you out.
As #evolutionxbox said. Try naming the component with UpperCamelCase. It's used to specify a React element
https://reactjs.org/docs/jsx-in-depth.html#specifying-the-react-element-type
Also, it is now common to create components as functions and not Classes. Of course it's up to you if you do prefer classes.
https://reactjs.org/docs/components-and-props.html#rendering-a-component

Invalid hook call - Material Ui

`× 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:
You might have mismatching versions of React and the renderer
(such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app`
I am new to react so this means I just follow tutorials from the internet and I'm trying to make a sidebar for my project. This sidebar is consist of a search box which includes a search icon from material-ui. After I install the #material-ui/icons and #material-ui/core and imported them to the javascript file (sidebar.js) that I'm working, this error pops-up. However, this invalid hook call says that the problem occurs at my other file (index.js) pointing at a line of code that starts with ReactDom.render( , although the react and react-dom are in the same version. This is the code from my sidebar.js:
import React from "react";
import SearchIcon from '#material-ui/icons/Search'
const Sidebar = () => {
return (
<div className="sidebar">
<div className="sidebar__header">
<div className="sidebar__search">
<SearchIcon className="sidebar__searchIcon"/>
<input placeholder="Search" className="sidebar__input"></input>
</div>
</div>
<div className="sidebar__threads"></div>
<div className="sidebar__bottom"></div>
</div>
)
}
export default Sidebar
And this is my code from the index.js
import React from "react";
import ReactDom from 'react-dom';
import './index.css';
import App from './App';
import { store } from './app/store';
import { Provider } from 'react-redux';
ReactDom.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);

Attempted import error: './components' does not contain a default export (imported as 'App')

I have the following ReactJS project structure and I'm getting the following error:
./src/index.js
Attempted import error: './components' does not contain a default export (imported as 'App').
My goal is to import components like this: import { App, Navbar } from 'components'; (notice the 'components') and not like ./components/App, ./components/App/index or so. To do that, I needed to add index.js in the components directory. I tried doing that by the following code, but I'm receiving the error above.
What's the reason? How do I solve it?
There are similar threads, but I'm already exporting it by export default App; in ./components/App/index.jsx. Maybe the reason is the .jsx extension?
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
components/index.js
export App from './App';
components/App/index.jsx
import React, { Fragment } from 'react';
import './style.css';
import { BrowserRouter as Router, Switch, Route, Redirect } from 'react-router-dom';
import NotAuthorizedRoute from '../../common/NotAuthorizedRoute';
import { Navbar, Home, User, Login } from 'components';
const App = () => {
return (
<Fragment>
<Router>
<Navbar />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/users" component={User} />
<NotAuthorizedRoute path="/sign-in" component={Login} />
<Redirect from="*" to="/" />
</Switch>
</Router>
</Fragment>
);
};
export default App;
components/App/style.css
What I tried:
I tried doing the following, like people said in this thread: Attempted import error: 'App' is not exported from './App'.
components/index.js
export { App } from './App'; // note the brackets
But then I got:
./src/components/index.js
Attempted import error: 'App' is not exported from './App'.
It seems you are having some confusions with ES6 export/import syntaxes. MDN documentation is very explicative, I would recommend you to check it.
The most important thing is to remember the difference between default and named export/import. (HINT: When you see brackets in export/import statements you are dealing with named ones)
In your specific case, you will have to do as follows:
./components/component-a.jsx
const ComponentA = () => {
return (
<MyComponent/>
);
};
export {ComponentA};
./components/component-b.jsx
const ComponentB = () => {
return (
<MyComponent/>
);
};
export {ComponentB};
./components/index.js
import {componentA} from './component-a.jsx';
import {componentB} from './component-b.jsx';
export {componentA, componentB};
./some-file.jsx
import {componentA, componentB} from './components';
./some-other-file.jsx
import {componentA} from './components';
This is the typical pattern to create a virtual export/import namespace for logical module classification.
Please note that I've not used default exports. There are several opinions about this, but I would recommend to not use them to avoid errors like the one you are having.
Please also note that you'll always have to specify the full relative path to the components directory. The only way to import things from 'components' is by having a components package installed in your node_modules directory.
Make sure you are not using the exported value componentA in {componentA}
remove `{}` and check

JSSProvider not generating class prefix with classNamePrefix

I'm using material-react in my React project. We are using material-react in both shell and micro-frontend. The class names generated by both shell and micro-frontend are being same viz., .jss1, .jss2 which is causing style collisions.
Im trying to generate unique class names for the micro-frontend, something like App1-{className} using JssProvider classNamePrefix prop, but still the classnames are generating as it is (.jss1, .jss2 etc). I have installed react-jss#10.0.0 as of now. I have tried many solutions from stackoverflow and github issues as well. But none of them are working for me.
import React from "react";
import ReactDOM from "react-dom";
import { JssProvider } from "react-jss";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import App from "./components/App";
import "./styles.css";
import { Provider } from "react-redux";
const routing = (
<JssProvider classNamePrefix="App1">
<Provider>
<Router>
<Switch>
<Route exact path="/" component={App} />
</Switch>
</Router>
</Provider>
</JssProvider>
);
ReactDOM.render(routing, document.getElementById("root"));
Following is the css classes that are getting generated in prod environment.
I need something like App1-{className} for the class names, so that they don't clash with other styles with similar names.
I have followed these stackoverflow links, but unfortunately none of them are working for me.
React Admin displays very messed up
https://github.com/marmelab/react-admin/issues/1782
Please help me solve this thing. I feel i'm missing something very basic.
You could use the seed option of createGenerateClassName function which is part of #material-ui/core/styles:
options.seed (String [optional]): Defaults to ''. The string used to uniquely identify the generator. It can be used to avoid class name collisions when using multiple generators in the same document.
import React from "react";
import ReactDOM from "react-dom";
import { StylesProvider, createGenerateClassName } from '#material-ui/core/styles';
import { Provider } from "react-redux";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import App from "./components/App";
import "./styles.css";
const generateClassName = createGenerateClassName({
seed: 'App1',
});
export default function App() {
return (
<StylesProvider generateClassName={generateClassName}>
<Provider>
<Router>
<Switch>
<Route exact path="/" component={App} />
</Switch>
</Router>
</Provider>
</StylesProvider>
);
}
This part of the material-ui documenation solved my issue.
https://material-ui.com/styles/api/#creategenerateclassname-options-class-name-generator
Strangely the JSSProvider solution was not working for me, whereas it was working for others. For those who faced similar issue, can use StyleProvider instead of JSSProvider.
Have you tried to install same versions of material-ui in all of your libraries?
I had the same problem, I have different material ui versions in my app and in my custom component library. Installing the same version works for me.

react-router-dom gives error

I have following implementation of "react-router-dom", but I am not able to get it working. can someone guide me what's the underlying issue.
App.jsx
import React from "react";
import Main from "../components/Main";
import Home from "../components/Home";
import { BrowserRouter, Match, Miss, Link } from 'react-router-dom';
const App = () => (
<BrowserRouter>
<div>
<Match exactly pattern="/" component={Main} />
<Match pattern="/home" component={Home} />
</div>
</BrowserRouter>
);
export default App;
Index.jsx
import React from "react";
import ReactDOM from "react-dom";
import Main from "./components/Main";
import Home from "./components/Home";
import Page from './components/Page';
import App from "./config/App";
ReactDOM.render(
<App/>,
document.getElementById('app')
);
I get the following error :
Please refer to the docs of React Router v4
Match and Miss are from previous versions of react-router-v4.alpha
With the current stable release of v4. You should use Route instead of Match. Miss is not there anymore.
I think this should solve your problem.
First of all, you should use Route instead of match.
Second, imports are case sensitive.
Third, match as per the doc you will get match object as prop.

Categories