Trying to add a to an existing React component but running into some difficulties. Given the following code
import { Link } from 'react-router-dom';
require('./NavBar.scss');
class NavBar extends React.Component {
authButton() {
console.log(Link)
const route = this.props.currentUser ? 'logout' : 'login';
return <Link to={ `/${route}` }>route</Link>
}
The navbar component fails to render and I get this error
Uncaught TypeError: Object(...) is not a function
at eval (react-router-dom.js:198)
If I change the "to" prop to a function like this
return <Link to={ () => return `/${route}` }>route</Link>
the component does actually render but I get this message "checkPropTypes.js:19 Warning: Failed prop type: Invalid prop to supplied to Link."
Any idea on what could be causing this. Have used this component on the same version of react-router-dom (5.0.0) on other projects without issue.
Try to use it with withRoute from react-router-dom. In the bottom of the file, export default navbar, write this line
export default withRoute(navbar)
Don't forget import it from react-router-dom.
There's usually a problem with react-router-dom when the component isn't included in Route element in the 'main component' such App.js.
<Route path='/' component={}
Something like that.
I'm assuming this since a lot of people get this problem with React-router-dom.
Related
In App.js I have the following route:
<Route path="/Comp1/:catid">
<Comp1 />
</Route>
This route can be called by clicking this link with a single parameter:
<Link to={'/Comp1/' + catid}>Comp1 </Link>
The parameter catid always has a certain value.
Comp1 is a component defined as follows:
import React, { Component } from 'react';
import { useParams } from 'react-router-dom';
export default class Comp1 extends Component {
componentDidMount() {
const params = useParams();
const { catid } = params.catid;
console.log(catid);
}
componentDidUpdate() {
}
render() {
return (
<div>
Hello, I am class Comp1
</div>
);
}
};
But what is happening now is at runtime, I am getting the following debug output:
'react-router-dom' does not contain an export named 'useParams'
--edit--
Installed version of react-router-dom is 4.2.2.
Definitely a version issue. Also discussed in this official issue.
Solution: Make sure you are using react-router-dom#>=5.1, since that particular hook was introduced in the 5.1 release.
If you have trouble getting modules installed at a proper version, then is the perfect time to practice just that, especially since it is very likely going to happen again and again, if you don't.
I am Trying to use react-router-dom. When I export my component as
class RandomComponent { // component code}
export default RandomComponent;
and use this as a component in Route as following -
<Route path="/" exact component={RandomComponent} />
I get following warning in chrome console -
Warning: Failed prop type: Invalid prop component of type object supplied to Route, expected function
But When I export my component using
export class RandomComponent{ // component code}
same piece of code starts working, can someone explain me why this is happening? thanks in advance.
You most probably tried to import your component with curly braces even though it is a default export.
DEFAULT EXPORT:
If you use export your component with default specified (default export), you need to import it without curly braces like this:
import RandomComponent from '../pathToComponent';
NAMED EXPORT:
But if you export your component without default specified (named export), you need to import it with curly braces like this:
import { RandomComponent } from '../pathToComponent';
Do note that you can only have one default export from a single file but as many named exports as you want from a single file.
Warning: Failed prop type: Invalid prop component of type object supplied to Route, expected function
the passed prop is not a component but is an object. your class should extend React.Component
import React, {Component} from 'react'
class RandomComponent extends Component {/*your code*/}
This appears to be a bug in react-router prior to version 4.4.
At the time of writing the latest version is 5.2, and using that version fixed the issue for me:
npm install --save react-router#latest
If you're using react-router-dom you may also want to update that.
Be aware that if you are having this problem your react-router is at least 2 major versions out of date; and there may be significant work required to get your routes to work in the latest version. Update packages across major version boundaries cautiously.
I have a trouble regarding this issue on react native navigation by the way I am using redux.
Listserviceaction.js
contains webservicecall component is being imported here
import ListComponent from '../components/ListComponent';
Listactiontype.js
contains action ActionTypes
export const SERVICE_PENDING = 'service_pending' and etc.
listcomponent.js
the component, renders data on a list etc
reducers
and then the reducer Part
scenes/List.js
store binding will be done within the initial point of the application and passed down to the other application components as shown below.
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import store from '../reducers/index';
import ServiceAction from '../actions/listserviceaction';
import { Container, Content, Picker, Button, Text } from "native-base";
export default class RenderList extends Component {
render() {
return (
<Provider store={store}>
<ServiceAction />
</Provider>
);
}
}
now after the component is being loaded and when i click onPress={() => this.props.navigation.navigate("ProfileScreen")} on my
listcomponent it fires an error (undefined is not an object .. this.props.navigation.navigate) any problem ? any better solution?
Thank You.
Include on your ServiceAction the this.props.navigation something like this:
<ServiceAction navigation={this.props.navigation}/>
because the props.navigation are by default on your parent component
and on ServiceAction component you will access to navition like:
..
goToSignUp() {
this.props.navigation.navigate('SignUp');
}
..
For me also was confusing before. Cheers!
for navigating from one screen to other, both the screens should be in StackNavigator. Can you please show your stacknavigator and code of the screens you are trying to navigate between.
for using react navigation you must do this steps:
1: npm i react-navigation --save
2: npm link react-navigation
3: modify a top level class for your stack like this :
import page_1 from 'YOUR_PAGE1_PATH'
import page_2 from 'YOUR_PAGE2_PATH'
import { createStackNavigator } from 'react-navigation'
export default createStackNavigator({
p1 : page_1 //remember the first modified shown first
p2 : page_2
})
then in page_1 if you want to navigate to page 2 :
onPress(()=> this.props.navigation.navigate('p2' , 'maybe other params'))
Note : you must call p1,p2 instead of page_1 or page_2!
I am working on a React app that is 'remote controlled' and am trying to connect the app's tab navigation via Pusher. I am using react-router-dom and have set up my connection to Pusher and the channels it listens to in the componentDidMount. I need to have the app change URL navigation each time a message is returned but cannot figure out what the correct way to 'push' it is. I have google many threads about programmatically navigating react-router-dom and have tried this.history.push(), this.props.history.push() and it's always throwing an error that history is undefined. The listeners reside in the same Component as the routing itself.
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import axios from 'axios';
import Pusher from 'pusher-js';
import Component1 from './Component1';
import Component2 from './Component2';
export default class AppRouter extends Component{
componentDidMount() {
const pusher = new Pusher('8675309', { cluster: 'us2', encrypted: true });
const nav_channel = pusher.subscribe('nav');
nav_channel.bind('message', data => { this.props.history.push(data.message) });
}
...
render(){
return(
<Router>
<Switch>
<Route path='/path1' render={() => <Component1 navigate={this.handleNavChange} />} />
<Route path="/path2" render={() => <Component2 navigate={this.handleNavChange} />} />
</Switch>
</Router>
)
}
}
I need the app to change the URL or the routing each time the message is received from another connected app but I cannot figure out how to make react-router-dom (v4) do it within the same component as the Router itself. Any information or pointing me to a resource would be highly appreciated.
You need to use the withRouter decorator from React-Router to get access to match, location, and history.
import { withRouter } from 'react-router'
Wrap your component when exporting
export default withRouter(yourComponent)
Then you will have access to history from props.
https://reacttraining.com/react-router/core/api/withRouter
To add on to andrewgi's answer:
After using withRouter() on your component, OR a parent component,
try the following code in your component:
static contextTypes = {
router: PropTypes.object,
location: PropTypes.object
}
These should be defined, you can try console.log(this.context.router, this.context.location)
Then, to navigate programmatically, call
this.context.router.history.push('/someRoute');
Note: the context API is not stable. See Programmatically navigate using react router and https://reactjs.org/docs/context.html#why-not-to-use-context.
When I run the my app on browser I get on my console:
"Warning: Failed propType: Invalid prop 'component' supplied to
'route'"
My routes file:
import { Route, IndexRoute } from 'react-router';
import React from 'react';
import App from './container/App';
import PContainer from './container/PContainer/PContainer';
import PView from './container/PView/PView';
const routes = (
<Route path="/" component={App} >
<IndexRoute component={PContainer} />
<Route path="/Posts View" component={PView} />
</Route>
);
export default routes;
My PView file:
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
class PView extends Component {
render() {
return (
<div>
<h1>List of Posts</h1>
</div>
);
}
}
export default connect()(PView);
Can anyone tell me why I am getting this error?
I met the same issue as you.
When I put a connect() component into <Route />, this warning must be there. If the component is not a connect() one, then the issue will not be there.
Solution
You can change the line
<Route path="/Posts View" component={PView} />
to
<Route path="/Posts View" render={(props) => <PView {...props} />} />
then the issue should go away.
Thinking
Look at the document of React-router
component should be used when you have an existing component (either a
React.Component or a stateless functional component) that you want to
render. render, which takes an inline function, should only be used
when you have to pass in-scope variables to the component you want to
render.
So when you would like to define a route of connect() component, you are implicitly going to pass some additional props into it, then according to the document you should use render instead of component. I guess this is the reason of warning happened.
Make sure that App, PContainer, and PView are all valid React components. Check module's imports and exports. Export should be with "default", otherwise you should use named import: import {somecomp} from './somecomp'. Check your routes to components.
Your routes look a bit weird: './container/PContainer/PContainer' and './container/PView/PView'.
Maybe it should be './container/PContainer' and './container/PView', if you don't have PContainer and PView folders.
Recently, I have been through this issue. I found that if you have any imported component which is empty or returning nothing then this issue arises because react could not consider it as a valid component.
Have a look if you have any component that you might have left empty.