React error "Uncaught Invariant Violation" when using react-router - javascript

I'm stumped on what this error message could mean or why I only get it when trying to use react-router. The app works fine if I render a component directly like this: render(<App />, document.getElementById('root'));
But when I try to use the <BrowserRouter>, <Match>', & <Miss> elements from react-router, like this: render(<Main />, document.getElementById('root'));, I get the following error message from my console:
Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. Check the render method ofMain.
I'm also seeing this error in an invariant.js file: error.framesToPop = 1; // we don't care about invariant's own frame error = Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined...
Here's my index.js file
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter, Match, Miss } from 'react-router';
import App from './App';
import SineWave from './SineWave';
import NotFound from './NotFound';
import './index.css';
const Main = () => {
return (
<BrowserRouter>
<div>
<Match exactly pattern="/" component={App} />
<Match exactly pattern="/lesson-one" component={SineWave} />
<Miss component={NotFound} />
</div>
</BrowserRouter>
)
}
render(<Main />, document.getElementById('root'));
Does anyone have any idea what's wrong here?
I'm not sure if this is useful, but here's the webpack data with some clues as to where the error might be:
function invariant(condition, format, a, b, c, d, e, f) {
if (true) {
if (format === undefined) {
throw new Error('invariant requires an error message argument');
}
}
if (!condition) {
var error;
if (format === undefined) {
error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
} else {
var args = [a, b, c, d, e, f];
var argIndex = 0;
error = new Error(format.replace(/%s/g, function () {
return args[argIndex++];
}));
error.name = 'Invariant Violation';
}
error.framesToPop = 1; // we don't care about invariant's own frame
throw error;
}
}
module.exports = invariant;
**Additional components that may be causing the problem:
Here's my App.js file:
import React from 'react';
import './App.css';
import Header from './Header';
import Instructions from './Instructions';
import SineWave from './SineWave';
const App = (props) => {
return (
<div className="App">
<div className="header">
<Header />
</div>
<div className="body">
<div className="instructions">
<Instructions instructionText="Here are the instructions!"/>
</div>
<div className="SineWave">
<SineWave soundText="This is a sound."/>
</div>
</div>
</div>);
};
export default App;
And here is the SineWave.js file, which is also referenced:
import React from 'react';
class SineWave extends React.Component {
render() {
return (
<div>
<button classID="playSine">PLAY SINEWAVE</button>
<p>{this.props.soundText}</p>
</div>
)
}
}
export default SineWave;
And finally, the NotFound.js file:
import React from 'react';
class NotFound extends React.Component {
render() {
return (
<h2>Not Found!111!!</h2>
)
}
}
export default NotFound;

SOLVED: It turns out that <BrowserRouter> can only be used in react-router v4 ... I was using v2.8, which is the version that's is installed when you type npm install --save react-router. If you want to use react-router v4 you'll need to use npm install --save react-router#next. Here's a link to the v4 branch on GitHub: https://github.com/ReactTraining/react-router/blob/v4/README.md–

Have you tried rendering Main like this?:
render(
(
<Main/>
),
document.getElementById("selector")
);
Note that I have surrounded the Main component in brackets.
It might be a dumb solution, but I know I've encountered this before and I believe it's an issue with rendering.

Related

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. React

Error:
"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of App."
index.js
import { registerRootComponent } from 'expo';
import App from './App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in the Expo client or in a native build,
// the environment is set up appropriately
registerRootComponent(App);
App.js
import React, { Component } from 'react';
import { NavigationCointainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Favoritos from './Favoritos';
import InfoGeneral from './InfoGeneral';
import Principal from './Principal';
const Stack = createStackNavigator();
export default class App extends Component {
render(){
return(
<NavigationCointainer>
<Stack.Navigator initialRouteName='Principal'>
<Stack.Screen name='Principal' component={Principal}/>
<Stack.Screen name='InfoGeneral' component={InfoGeneral}/>
<Stack.Screen name='Favoritos' component={Favoritos}/>
</Stack.Navigator>
</NavigationCointainer>
);
};
}
This is a very common error, it means you are trying to render undefined as a component. This usually happens in circumstances like this:
MyComponent.js:
function MyComponent() {
return <View />;
}
App.js
import { MyComponent } from './MyComponent';
export default function App() {
return <MyComponent />;
}
Can you spot what is missing? It's export from MyComponent.js. In App.js, MyComponent is undefined because there is no such export. To fix it, you would do this:
MyComponent.js:
export function MyComponent() {
return <View />;
}
I had this error when I tried to get rid of warnings about PascalCase.
The warning:
Imported JSX component text must be in PascalCase or
SCREAMING_SNAKE_CASE react/jsx-pascal-case
I changed all components in my React Redux Form from Control.text, Control.select, Control.textarea to Control.Text, Control.Select, Control.TextArea and started getting this error.
I changed
<Control.Text />
<Control.Select />
<Control.TextArea />
back to
<Control.text />
<Control.select />
<Control.textarea />
and the error was gone.

Cannot get SVG as a component to render in CRA

I've written the following TypeScript component:
import React from 'react'
import cx from 'classnames'
/* import SVGs */
import { ReactComponent as Phone } from '../images/phone.svg'
import { ReactComponent as AtDesk } from '../images/at-desk.svg'
import { ReactComponent as Available } from '../images/available.svg'
import { ReactComponent as Blushing } from '../images/blushing.svg'
import { ReactComponent as Skills } from '../images/skills.svg'
import { ReactComponent as Smile } from '../images/smile.svg'
import { ReactComponent as Beach } from '../images/beach.svg'
const selectMiniMe = (name: string): any => {
switch (name) {
case 'available' :
return <Available />
case 'at-desk':
return <AtDesk/>
case 'blushing':
return <Blushing />
case 'skills':
return <Skills />
case 'phone':
return <Phone />
case 'beach':
return <Beach />
case 'smile':
default:
return <Smile />
}
}
/* Import Types */
import Props from './types/props'
/* import Styles */
import styles from './styles.module.scss'
/* Render Component */
export const MiniMe: React.FC<Props> = ({ name, width, position, classes}: Props) => {
return <div className={cx(styles['mini-me'], styles[`w-${width}`], classes)}>
{ selectMiniMe(name) }
</div>
}
export default MiniMe
This component renders without issue as a story in storybook. Everything looks and works exactly as expected and no errors are reported.
When I try to import that component into a brand new Create-React-App TypeScript app. I get the following error:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `MiniMe`.
I suspect the issue is loader related but as far as I can tell, I'm doing everything the way that CRA is already configured to work with so I have no idea where it's failing.
For additional reference, here is a link to the repo: https://github.com/foxleigh81/alex-foxleigh-portfolio/tree/2020
I've also managed to find a reference to this exact issue - which as far as I can tell was actually fixed in CRA in 2018, so I've no idea why I'm getting this issue here: https://github.com/facebook/create-react-app/pull/5573
Try to declare the svg module
add this to
// / <reference types="react-scripts" /> declare module '*.svg';
in your react-app-env.d.ts file.
Looking at your repository it seems you are using learna and react setup and are not using create-react-app completely, as I don't see all dependencies that are added to new react app created using create-react-app there in your codebase and hence I am not sure using svg as component will work.
That being said, that will not prevent you from using img tag. I have updated your code and it is working as expected:
import React from 'react'
import cx from 'classnames'
/* Import Types */
import Props from './types/props'
/* import SVGs */
import Phone from './images/phone.svg'
import AtDesk from './images/at-desk.svg'
import Available from './images/available.svg'
import Blushing from './images/blushing.svg'
import Skills from './images/skills.svg'
import Smile from './images/smile.svg'
import Beach from './images/beach.svg'
/* import styles */
import styles from './styles.module.scss'
/* Render component */
export const MiniMe: React.FC<Props> = ({ name, width, position, classes}: Props) => {
const selectMiniMe = (name: string): any => {
switch (name) {
case 'available' :
return <img src={Available} />
case 'at-desk':
return <img src={AtDesk} />
case 'blushing':
return <img src={Blushing} />
case 'skills':
return <img src={Skills} />
case 'phone':
return <img src={Phone} />
case 'beach':
return <img src={Beach} />
case 'smile':
default:
return <img src={Smile} />
}
}
return <div className={cx(styles['mini-me'], styles[`w-${width}`], classes)}>
{selectMiniMe(name)}
</div>
}
export default MiniMe

How can pass a props to a variable?

I'm trying "hydrate" props from elements to child components that will render. The problem is that I can't figure out how I can do it with my configuration.
I have seen this answer, I tried to adapt it, but so far I'm getting errors (see bottom).
For a bit of background, I'm developing a Rails based application that uses React for the front end. So I don't use React router or such, it just "displays" the datas.
Here is how I set everything up:
front.js (where everything gets rendered)
import React from 'react';
import ReactDOM from 'react-dom';
import extractActionName from './lib/extractActionName';
import {elementForActionName} from './lib/elementForActionName';
import 'jquery';
import 'popper.js';
import 'bootstrap';
let actionName = extractActionName();
let value = "value";
let renderElement = function (Element, id) {
ReactDOM.render(
<Element value={value} />,
document.getElementById(id)
);
};
renderElement(elementForActionName[actionName], actionName);
lib/elementForActionName.js
import React from 'react';
import Homeindex from '../home/home';
import Contact from '../home/contact';
// This files create an associative array with id React will be
// looking for as a key and the component as value
export const elementForActionName = {
'index': <Homeindex />,
'contact': <Contact/>,
};
lib/extractActionName.js
export default function extractActionName() {
// The body contains classes such as "home index", so
// I return the "action name" of my controller (home) to
// front.js so I will render the good component
return document.body.className.split(' ').pop();
}
home/home.js
import React from 'react';
import Header from '../layout/header';
import Footer from '../layout/footer';
export default class homeIndex extends React.Component {
render() {
return(
<div>
<Header/>
<h1>Hello this will be the content of the landing page hello</h1>
<Footer/>
</div>
)
}
}
My problem is that I'd like to make an Ajax call in my "front.js" file, then transmit the received data (here, "value"). The error I'm getting is the following:
Uncaught Error: Element type is invalid: expected a string (for
built-in components) or a class/function (for composite components)
but got: object.
I'm lacking experience with React, how can I resolve this problem?
Thank you in advance.
You are currently returning the instance of a component:
export const elementForActionName = {
'index': <Homeindex />, <--- here
'contact': <Contact/>,
};
And then attempting to instantiate it again:
let renderElement = function (Element, id) {
ReactDOM.render(
<Element value={value} />, // <--- here
document.getElementById(id)
);
};
Instead, just use the component class:
export const elementForActionName = {
'index': Homeindex,
'contact': Contact,
};

Bundle.js not recognizing one of my files?

Please bear with me because I am a javascript newbie, and just starting to learn react.
I am trying to make a small app but I keep getting an error that one of my files is not found... specifically this:
bundle.js:56 Uncaught Error: Cannot find module "./components/search_bar"
My file structure is that I have my index.js in a folder called src, then my search bar(search_bar.js) in a folder called components. I have triple checked the spelling on them but I continue to get this error.
This is my index.js
import SearchBar from './components/search_bar';
import React from 'react';
import ReactDOM from 'react-dom';
//Create a componant (some /HTML)
const API_KEY = 'AIzaSyC3Z3qTpvAacDLYEIxaueKflFJbWvdIHsw';
const App = () => {
return (
<div>
<SearchBar />
</div>
);
}
// Put that componant on the page (the DOM)
ReactDOM.render(<App />, document.querySelector('.container'));
And this is my search_bar.js
import React, { Component } from 'react';
class SearchBar extends Component {
contructor(props) {
super(props);
// when user updates the search bar this term will get updated.
this.state = { term: ''};
}
render() {
//update state
//use set state everywhere besides constructor!!
return (
<div>
<input onChange={event => this.setState({term: event.target.value})}
/>
Value of the input: {this.state.term}
</div>
);
}
}
export default SearchBar;
Any Ideas as to what I am doing wrong here?
Can you confirm the following directory structure?
my_project/src/index.js
my_project/src/components/search_bar.js
It seems like your current directory structure might instead look like this:
my_project/src/index.js, my_project/components/search_bar.js
AHHH I left an 's' out of constructor... so search_bar.js was unable to compile. I have been looking at this for about an hour now...

Uncaught Error: Cannot Find Module When Using Dynamic Import for JavaScript

I'm using Create-React-App and am looking to use the dynamic import() supported by webpack 2.0 to import a module based on a variable string.
I've looked at the official proposal (https://github.com/tc39/proposal-dynamic-import) and it seems possible to do something like this:
import(`./language-packs/${navigator.language}.js`)
But it breaks when I try something similar.
AppRoutes.js
import LazyLoad from 'services/LazyLoad';
export class AppRoutes extends React.Component {
render() {
return (
<Switch>
<Route
exact path="/"
render={(matchProps) => (
<LazyLoad
absoluteModulePath='pages/default/HomePage'
getComponent={() => import('pages/default/HomePage')}
{...matchProps}
/>
)}
/>
</Switch>
);
}
}
export default AppRoutes;
pages/default/HomePage/index.js
import React from 'react';
export const HomePage = () => {
return (
<div>
I'm the default HomePage
</div>
);
}
export default HomePage;
BROKEN services/LazyLoad/index.js
import React from 'react';
export class LazyLoad extends React.Component {
...
componentDidMount() {
import(this.props.absoluteModulePath) // Critical dependency: the request of a dependency is an expression
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
...
}
export default LazyLoad;
Error:
But when I change the LazyLoader to
WORKING services/LazyLoad/index.js
import React from 'react';
export class LazyLoad extends React.Component {
...
componentDidMount() {
this.props.getComponent()
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
...
}
export default LazyLoad;
it works.
The absolute paths is something built into create-react-app with the help of environment variables.
.env
NODE_PATH=src/
I require dynamically loading modules this way to build a proof of concept for multi-tenancy. How can I fix the broken LazyLoad such that I can pass a string as a prop and have the LazyLoad component dynamically load the component from that string prop?
Only partially dynamic statement are allowed for import().
In your AppRoutes.js you could do this:
...
<LazyLoad
modulePath='HomePage'
getComponent={() => import('pages/default/HomePage')}
{...matchProps}
/>
then in your LazyLoad Component you do:
componentDidMount() {
import(`pages/default/${this.props.modulePath}/index.js`)
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
Fully dynamic statements, such as import(foo), will fail because webpack requires at least some file location information.The import() must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files.
https://webpack.js.org/api/module-methods/#import-

Categories

Resources