'Router'/'GlobalStyles' cannot be used as a JSX component - javascript

I'm having this issue on my React application:
'Router' cannot be used as a JSX component.
Its instance type 'Router' is not a valid JSX element.
The types returned by 'render()' are incompatible between these types.
It's also happening on a Global Styles component I created
'GlobalStyles' cannot be used as a JSX component.
Its instance type 'Component<ThemedGlobalStyledClassProps<{}>
This is my App.tsx file:
import {BrowserRouter, Router} from 'react-router-dom';
import { Slide, ToastContainer } from "react-toastify";
import Routes from "./routes";
import GlobalStyles from "./styles/global";
import Header from "./components/Header";
import Aside from "./components/Aside";
import { CartProvider } from "./hooks/useCart";
import history from "./history";
import { AuthProvider } from "./Context/AuthContext";
const App = (): JSX.Element => {
return (
<>
<Aside />
<AuthProvider>
<Router history={history}>
<CartProvider>
<GlobalStyles />
<Header />
<Routes />
<ToastContainer autoClose={3000} transition={Slide} />
</CartProvider>
</Router>
</AuthProvider>
</>
);
};
export default App;
I'm using the version 18 of React and there's what I've tried so far:
Deleting node_modules and running yarn install
Reverting React version to 17~
Reinstalling React and React Router

First at all you have to import BrowserRouter as Router like the following code:
import { BrowserRouter as Router, } from "react-router-dom";
GlobalStyles probably it not a component.
Here two way to create a component in React.
1-) Function Components must be like following:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
2-) Class Components:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

Your styled-components might be using old versions of #types/react. You can confirm by checking the version of react types in node_modules/types/styled-components.
For me adding yarn resolutions helped to solve the problem (if you are using yarn as well).
Try adding this to your package.json file.
"resolutions": {
"#types/react": "^18.0.0"
}
Unfortunately it will (might???) not work if you are using npm.

Related

Invalid hook call error when wrapping MuiThemeProvider within App

I get the following error when I wrap MuiThemeProvider in App.js. The page will not load at all. I've used it similarly in other projects, so not sure why this is happening.
react.development.js:1476 Uncaught 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
App.js
import React from 'react'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import Home from './views/Home'
import ProjectDetailsForm from './components/ProjectDetailsForm/ProjectDetailsForm'
import { MuiThemeProvider } from '#material-ui/core/styles'
import theme from './styles/theme'
function App() {
return (
<MuiThemeProvider theme={theme}>
<Router>
<div className="app">
<Routes>
<Route
path="/"
element={[
<Home key="1"></Home>,
<ProjectDetailsForm key="2"></ProjectDetailsForm>
]}></Route>
</Routes>
</div>
</Router>
</MuiThemeProvider>
)
}
export default App
theme.js
// import { common } from '#material-ui/core/colors'
import { createTheme } from '#material-ui/core/styles'
// import { black } from '#mui/material/colors'
const theme = createTheme({
components: {
MuiFormLabel: {
styleOverrides: {
root: {
color: '#000'
}
}
},
MuiInputLabel: {
styleOverrides: {
root: {
color: '#000'
}
}
}
}
})
export default theme
This issue can happen when you're React tries to load twice. For example, if I make my own library that uses React, and then import it locally into a project that also uses React. What's in this file ./components/ProjectDetailsForm/ProjectDetailsForm'?
Solved:
I realized I hadn't yet installed #material-ui/core. Once I tried, I was getting 'could not resolve dependency errors'. Had to use legacy MUI dependencies due to conflicts with React 18.
Found the fix here

Class based component. Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component />

So, I'm doing some assignment and I get the following error when running my react app (Should be a dynamic URL like /item/n):
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
at Routes (http://localhost:3000/static/js/bundle.js:35605:5)
at Router (http://localhost:3000/static/js/bundle.js:35538:15)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:35014:5)
index.js:
import React from 'react'
import ReactDOM from 'react-dom'
import {
BrowserRouter as Router,
Routes,
Route
} from "react-router-dom";
import ProductMainView from './components/productMainView'
const rootElement = document.getElementById('root')
ReactDOM.render(
<Router>
<Routes>
<Route exact path="/item/:item_id"
element={(props) => <ProductMainView id={props.params.id} />} />
</Routes>
</Router>,
rootElement
);
productMainView.jsx:
import React, { Component } from 'react'
class ProductMainView extends Component {
componentDidMount() {
console.log(this.props)
let id = this.props.match.params.item_id
}
render() {
return <h1>Placeholder</h1>
}
}
export default ProductMainView
Yes, I know that class-based component are kinda obsolete, but I'm limited by the assignment.
Note: If the method of getting the id to the component is wrong, other ways would be welcome.
Note v2: I'm usign react-router v6.2.2

react-redux-react-router v4 url, updates but the component does not

First off, I have read through just about every example I can find and looked through various boilerplates to see how others have done this. I am having issues loading pages when clicking <Link>'s with react-router v4. I have also installed the package react-router-connected and have been trying that out as well but no improvement can be seen (however it shows the changes in the redux-logger which is nice).
Currently, the url updates just fine and if I manually change the url and press enter, then the next page will load. But, it will not redirect if I click a link. I am also using create-react app for the project, just for your reference. My actual app is setup as the exact example from usage with react-router in the official redux docs. For simplicity, I have changed my routes to only include links to basic components that do nothing but redirect to one another.
Root.js which houses my routes
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router'
// import App from './App';
import NewComponent from './NewComponent';
import OldComponentent from './OldComponent';
const Root = ({ store, history }) => (
<Provider store={store}>
<ConnectedRouter history={history}>
<Router>
<Switch>
<Route exact path='/' component={OldComponentent}/>
<Route path='/new' component={NewComponent}/>
{/* <Route path='/' component={App}/>
<Route path='/:filter' component={App}/> */}
</Switch>
</Router>
</ConnectedRouter>
</Provider>
)
export default Root;
Home component
import React from 'react';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
import { withRouter } from 'react-router';
import { Link } from 'react-router-dom';
import Button from 'material-ui/Button';
class OldComponent extends React.Component {
redirectPage = () => { this.props.dispatch(push('/new')); };
redirectPage1 = () => { this.props.dispatch(push('/')); };
render() {
return (
<div>
OLD COMPONENT
<Button onClick={this.redirectPage}>Redirect new</Button>
<Button onClick={this.redirectPage1}>Redirect /</Button>
<Link to='/new'>Redirect Link</Link>
</div>
)
}
}
export default withRouter(connect()(OldComponent));
Other basic component for redirection purposes
import React from 'react';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
import { withRouter } from 'react-router';
import { Link } from 'react-router-dom';
import Button from 'material-ui/Button';
class NewComponent extends React.Component {
redirectPage = () => { this.props.dispatch(push('/')); };
redirectPage1 = () => { this.props.dispatch(push('/new')); };
render() {
return (
<div>
NEW COMPONENT
<Button onClick={this.redirectPage}>Redirect /</Button>
<Button onClick={this.redirectPage1}>Redirect new</Button>
<Link to='/new'>Redirect Link</Link>
</div>
)
}
}
export default withRouter(connect()(NewComponent));
As you can see, they are essentially the same component with minor differences. The url will change to /new or / and will also update the pathname found in the ##router/LOCATION-CHANGE state objects created by react-router-connected package. The url will also change by clicking the <Link> tag but with no redirect.
Any help on how to approach this would be greatly appreciated.
The comment posted by #Supertopoz works this.props.history.push('/pathname') works. However, after setting that up, the <Link> now works as well. I am also using withRouter (which I was before) throughout, so that was another important factor in egtting it to work.

"Objects are not valid as a React child" appear only in IE

Objects are not valid as a React child. If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of Root.
This bug only appear in IE, i know a react child can't be an object, but i can't find any error in Root class
// Root.js
import React, { Component, PropTypes } from 'react'
import { Provider } from 'react-redux'
import { Router, browserHistory } from 'react-router'
import { syncHistoryWithStore } from 'react-router-redux'
import routes from './routes'
export default class Root extends Component {
render() {
const { store } = this.props
const history = syncHistoryWithStore(browserHistory, store)
return (
<Provider store={store}>
<div>
<Router history={history} routes={routes} />
</div>
</Provider>
)
}
}
// routes.js
import React from 'react'
import { Route } from 'react-router'
import Cookie from './libs/cookie'
import App from './app'
import MobileRouter from './routes/mobile'
import WebRouter from './routes/web'
export default (
<Route path="/" component={App}>
{ WebRouter }
{ MobileRouter }
</Route>
)
// App.js
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { browserHistory } from 'react-router'
class App extends Component {
constructor(props) {
super(props)
}
render() {
const { children } = this.props
return (
<div>
{ children }
</div>
)
}
}
Why
If you are using react-hot-loader v3 for hot-reloading in DEV environment you need to load react-hot-loader/patch after babel-polyfill does.
So Webpack's entry field should look like the following to work correctly with react 15.4.x, react-hot-loader v3 and webpack-dev-server.
Fix
entry: [
'babel-polyfill', // Load this first
'react-hot-loader/patch', // This package already requires/loads react (but not react-dom). It must be loaded after babel-polyfill to ensure both react and react-dom use the same Symbol.
'react', // Include this to enforce order
'react-dom', // Include this to enforce order
'./index.js' // Path to your app's entry file
]
Use
It is very useful to test a feature in your DEV environment on IE. You can now access your local app, with webpack running, on IE from a VM, local network, ngrok, etc.
“Objects are not valid as a React child” appear only in IE
Not true. This error will appear in all browsers if you use an object. You mostly likely have something like the following in your code
{someBool && someObj}
where someBool is only coming out true based on how your application state is in IE. if you did the same actions in any other browser you will get the same error.
Fix
Don't render an object. React can't handle it. And is giving you the correct error which you should fix i.e render something from the obj e.g.
{someBool && someObj.someStringProp}

React Router Renders Blank Page

I am building a react application and the react router renders a black page. I've googled around and can't seem to figure out what's going on.
index
import React from 'react'
import {render} from 'react-dom'
import routes from './routes'
render(routes, document.getElementById('root'))
routes
import React, { Component } from 'react'
import { Router, Route, hashHistory } from 'react-router'
import Home from './Home.js'
import Name from './Name.js'
//import level from './level.js'
//import level1 from './level1.js'
//import level2 from './level2.js'
//import result from './result.js'
const routes = (
<Router history={hashHistory}>
<Route path='/' component={Home} />
<Route path='/name' component={Name} />
</Router>
);
export default routes;
component that doesn't render by navigating /name
import React, { Component } from 'react'
import appState from './state.js'
import { Router } from 'react-router'
class Name extends Component {
constructor() {
super();
this.state = {username: ''};
}
onUpdateUser = (e) => {
this.appState.username = e.target.value;
Router.push({
pathname: '/level'
})
}
render() {
return (
<div className="row">
<div claassName="col-md-12">
<div className="nameBox">
<form className="form-inline" onSubmit={this.onUpdateUser()}>
<input type="text" className="form-control" placeholder="Desiered Username" onChange={this.onUpdateUser} value={this.state.username} />
<button type="submit" className="btn btn-success">Submit</button>
</form>
</div>
</div>
</div>
)
}
}
export default Name
Any help would be appreciated!PS The index route works fine.
What's the path of ./routes? Do you have a /routes/index.js file that consists of the code that you put for the routes?
Also I recommend that you use browserHistory instead of hashHistory for 'normal' url's, without hashes. More info about that here
For your Name class I would recommend you to use the withRouter Higher Order Component from React Router. This injects 'router' as a prop, inside of your component, so you can use this.props.router.push('/path').
this.appState actually does nothing right now. You're importing 'appState' that isn't being touched. Right now you're setting 'appState' within the Name component. Don't you mean to use this.setState({ username: e.target.value })?. It's also a better practice to use onUpdateUser(e) { code } instead of arrow functions for a class function.
I also see <form className="form-inline" onSubmit={this.onUpdateUser()}> - I think that onUpdateUser is currently called when rendering this component. You should do onSubmit={this.onUpdateUser} instead, so the function gets called when onSubmit is triggered. Or onSubmit={e => this.onUpdateUser(e)}, both things work.
What exactly are you trying to achieve with this code?
Edit:
I've added a gist in which I created the 'introduction - set username - choose level - rest' flow without using React Router. React Router isn't always necessary, especially for things in which you really want to control the flow of the views that have to be shown.
https://gist.github.com/Alserda/150e6784f96836540b72563c2bf331d0
Add this to your index file. You might need to use the actual Router from react-router.
//Import Dependencies.
import { Router } from 'react-router';
//Import Routes.
import routes from './routes/routes.js';
render(<Router routes={routes} />, document.getElementById('root'))
OR
Use ReactDom for react-dom instead of render.
import ReactDOM from 'react-dom';
ReactDom.render(<Router routes={routes} />, document.getElementById('root'));
To use this with current versions of react-router (v4) you need to use a switch element.

Categories

Resources