React Router route not rendering component - reactjs

I'm trying to redirect my HomePage Component to a different component with one click of a button. However, when the link is clicked it's changing the path in the browser URL but I'm not able to see any change (i.e., my new Addbook component is not being rendered inside Route).
App.js
import React, { Component, useState } from "react";
import axios from "axios";
import "./styles.css";
import HomePage from "./HomePage.js";
import Addbook from "./AddBook.js";
import {Router,Switch,Route, BrowserRouter} from "react-router-dom";
class App extends React.Component {
render()
{
return (
<BrowserRouter>
<Switch>
<Route exact path="/"><HomePage></HomePage></Route>
<Route path="/add"><Addbook></Addbook></Route>
</Switch>
</BrowserRouter>
);
}
}
export default App;
HomePage.js
import React from "react";
import {BrowserRouter, Link, Router, Switch, useHistory } from "react-router-dom";
class HomePage extends React.Component {
render() {
return ( <div>
<h1>Book Library</h1>
<BrowserRouter>
<Switch>
<Link to="/add"><button id="addbook">Add Book</button></Link>
<Link to="/search"><button id="searchbook">Search Book</button></Link>
</Switch>
</BrowserRouter>
</div>
)
}
}
export default HomePage
AddBook.js
import React from "react";
import axios from "axios";
const addBook = () => {
axios.post("http://localhost:3000/addbook",{
name: this.state.name,
author : this.state.author,
date: this.state.date,
category: this.state.category
}).then(response => response.data).then(data => {
console.log(data);
if(data=="added")
{
}
}, (error) => {
console.log(error);
});
}
class Addbook extends React.Component{
render(){
return (<div>
New Book<input type="text" onChange={(e)=>{
this.setState({name: e.target.value})
}} name="name" id="newbook"/>
Author<input type="text" onChange={(e)=>{
this.setState({author: e.target.value})
}} name="author" id="Author"/>
Date of Publish<input type="date" onChange={(e)=>{
this.setState({date: e.target.value})
}} name="date" id="dtofpub"/>
Category<input type="text" onChange={(e)=>{
this.setState({category: e.target.value})
}} name="category" id="category"/>
<button id="add" onClick={addBook}>ADD</button>
</div> )
}
}
export default Addbook;

you should update homePage like this :
import React from "react";
import {BrowserRouter, Link, Router, Switch, useHistory } from "react-router-dom";
class HomePage extends React.Component {
render() {
return (
<div>
<h1>Book Library</h1>
<Link to="/add"><button id="addbook">Add Book</button></Link>
<Link to="/search"><button id="searchbook">Search Book</button></Link>
</div>
)
}
}
export default HomePage

There is syntax error please replace
<Route exact path="/"><HomePage></HomePage></Route>
To
<Route exact path="/" component={HomePage}></Route>

Related

Failed prop type: Invalid prop 'component' supplied to 'Route': the prop is not a valid React component

When I click button visit store, I'm getting the above error. My react version is 17.0.2 & react-dom version is 17.0.2 & react-router-dom version is 5.3.0.
Index.js file
import React from "react";
import { render } from "react-dom";
import Router from "./components/Router";
import "./css/style.css";
render(<Router />, document.querySelector("#main"));
Router.js file
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import StorePicker from "./StorePicker";
import App from "./App";
import NotFound from "./NotFound";
const Router = () => (
<BrowserRouter>
<Switch>
<Route exact path="/" component={StorePicker} />
<Route path="/store/:storeId" component={App} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
);
export default Router;
When I console log this.myInput.value.value, I'm getting undefined. Please help.
StorePicker.js file
import { getFunName } from "../helpers";
class StorePicker extends React.Component {
myInput = React.createRef();
goToStore = (event) => {
// 1. Stop the form from submitting
event.preventDefault();
// 2. Get the text from the input
const storeName = this.myInput.value.value;
// 3. Change the page to /store/whatever user has entered
this.props.history.push(`/store/${storeName}`);
};
render() {
return (
<form className="store-selector" onSubmit={this.goToStore}>
<h2>Please enter a store name</h2>
<input
type="text"
required
ref={this.myInput}
placeholder="Store Name"
defaultValue={getFunName()}
/>
<button type="submit">Visit Store </button>
</form>
);
}
}
export default StorePicker;
This one is app.js file, And I have included component inside Route.js file.
import React from "react";
import Header from "./Header";
import Order from "./Order";
import Inventory from "./Inventory";
class App extends React.Component {
render() {
return (
<div className="catch-of-the-day">
<div className="menu">
<Header tagline="Fresh Seafood Market" age="21" />
</div>
<Order />
<Inventory />
</div>
);
}
}
export default App;
And I have created NotFound() component & included the same inside Route.js file.
const NotFound = () => (
<div>
<h2>Not Found!!!</h2>
</div>
);
export default NotFound();

React Router props.history

I'm a new to React.js with asp.net core, and I got an error that I don't understand.
I created protected route like that :
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import auth from './auth.js'
export const ProtectedRoute = ({ component: Component, ...rest }) => {
return (
<Route
{...rest}
render = {props => {
if(auth.estAuthentifier()){
return <Component {...props}/>
} else {
return <Redirect to={
{
pathname: "/",
state: {
from: props.location
}
}
} />
}
}}
/>
);
}
In my App.js, I added the protected route like that :
import React, { Component } from 'react';
import { BrowserRouter, Switch, Route } from 'react-router';
import { Login } from './components/Login'
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { ProtectedRoute } from './components/protected.route';
export default class App extends Component {
static displayName = App.name;
render () {
return (
<div>
<Switch>
<Route exact path="/" component={Login} />
<Layout>
<ProtectedRoute exact path="/home" component={Home}/>
</Layout>
<Route path="*" component={() => "404 NOT FOUND"}/>
</Switch>
</div>
);
}
}
And, the Layout component render all components with my NavBar included :
import React, { Component } from 'react';
import { Container } from 'reactstrap';
import { NavMenu } from './NavMenu';
import '../css/Layout.css';
export class Layout extends Component {
static displayName = Layout.name;
render () {
return (
<div className="conteneur-principal">
<NavMenu />
<Container>
{this.props.children}
</Container>
</div>
);
}
}
The problem is the next : I put the logout button in my navigation bar component but when I'm trying to logout and redirect to Login, i got the following error : TypeError: Cannot read property 'push' of undefined
NavMenu.js :
import React, { Component } from 'react';
import { NavLink } from 'reactstrap';
import { Link } from 'react-router-dom';
import auth from './auth';
import { withRouter } from 'react-router-dom';
import '../css/SideBarNav.css';
export class NavMenu extends Component {
static displayName = NavMenu.name;
constructor(props) {
super(props);
console.log(this.props);
this.deconnexion = this.deconnexion.bind(this);
}
deconnexion = () => {
auth.logout(() => {
this.props.history.push('/'); //LINE IN ERROR
})
}
render () {
return (
<div className="conteneur-menu">
<img src="images/familieu-logo-clear.png" alt="logo-familieu" title="logo-familieu" className="is-clickable logo-familieu"/>
<div className="conteneur-link">
<NavLink tag={Link} className="menu-link" to="/">Home</NavLink>
</div>
<input type="button" value="Déconnexion" className="btn-deconnexion" onClick={this.deconnexion}/>
</div>
);
}
}
What should I do to make my logout button work ?
Thanks alot
In NavMenu.js you are importing the withRouter, but is not used.
Wrap the export of component with withRouter like this:
export default withRouter(NavMenu);

Component not showing up in react router with laravel

I am new to React and I am trying to display a react route using react router dom but the matching component is not coming up. I have looked at answers from other OS questions related but no help. Here is my app.js file
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import AdminLogin from './AdminLogin';
export default class AdminApp
extends Component {
render() {
return (
<Router>
<Switch>
<div className="App">
<Route path="/" exact={true} component = {AdminLogin} />
</div>
</Switch>
</Router>
);
}
}
if (document.getElementById('app')) {
ReactDOM.render(<AdminApp />, document.getElementById('app'));
}
When i inspect my html file i get this
<div id="app">
<div class="App" location="[object Object]" computedmatch="[object Object]"></div>
</div>
this is my adminLogin component
import React, {Component} from 'react';
import {adminLogin} from './UserFunctions';
export default class AdminLogin extends Component {
constructor(){
super()
this.state = {
email: '',
password: '',
errors: {}
}
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e){
this.setState({ [e.target.name]: e.target.value })
}
onSubmit(e){
e.preventDefault;
const user = {
email : this.state.email,
password : this.state.password
}
adminLogin(user).then(res => {
if(res) {
this.props.history.push('/dashboard');
}
})
}
render(){
return (
<div className="kt-grid kt-grid--ver kt-grid--root">
<div className="kt-grid kt-grid--hor kt-grid--root kt-login>
<h1>Login Now</h1>
</div>
</div>
)
}
}
This only works if you are trying the root path (/). If you need to render this component at a subpath (e.g. /foo/bar/login), that should be defined as the route path.
<Route path="/foo/bar/login" exact={true} component = {AdminLogin} />

React-Router-Dom Link not working in a nested component. Update url parameters, but component doesn't load on click. Works if I refresh after click

I have a NavBar that's on multiple pages that allows me to search for an user. After the searching, clicking on it should re-direct me to the user page via Link from react-router-dom. The problem is this only works on the main page, and doesn't work when clicking from an user's page.
I've tried adding WithRouter to all my related components (containers, parents, and the children). Also tried fiddling with the Route pathing / exact pathing syntax to no avail.
*Removed components imports and non-relavant code for clarity.
/app.jsx
import React from 'react';
import { Provider } from 'react-redux';
import {
Route,
Redirect,
Switch,
Link,
HashRouter,
withRouter,
} from 'react-router-dom';
import { AuthRoute, ProtectedRoute } from '../utils/route_utils';
const App = () => (
<div className="main">
<HashRouter>
<Switch>
<AuthRoute exact path="/" component={LoginContainer} />
<AuthRoute exact path="/signup" component={SignupContainer} />
<ProtectedRoute exact path="/feed" component={FeedContainer} />
<ProtectedRoute exact path="/users/:userId" component={GreetingContainer} />
<ProtectedRoute exact path="/posts/:postId" component={PostShowContainer} />
<ProtectedRoute exact path="/upload" component={Upload} />
<ProtectedRoute exact path="/accounts/edit" component={AccountsEditContainer} />
<Route component={Errors} />
</Switch>
</HashRouter>
</div>
);
export default withRouter(App);
/greeting_container.jsx
import React from 'react';
import { withRouter } from 'react-router-dom';
const mapStateToProps = (state, ownProps) => {
...
};
const mapDispatchtoProps = (dispatch) => ({
....
});
export default withRouter(connect(mapStateToProps, mapDispatchtoProps)(Greeting));
/greeting.jsx
import React from 'react';
import { Link } from 'react-router-dom';
import NavBarContainer from '../nav_bar/nav_bar_container';
class Greeting extends React.Component {
constructor(props) {
super(props);
this.renderPosts = this.renderPosts.bind(this);
}
render() {
if (!this.props.user) return null;
const profileUser = parseInt(this.props.match.params.userId)
const user = this.props.user
return (
<div className="user-page-container">
<Modal currentUser={user} />
<NavBarContainer />
</div>
}
export default Greeting;
/nav_bar_container.jsx
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import NavBar from './nav_bar';
const mapStateToProps = (state) => {
....
};
const mapDispatchToProps = (dispatch) => ({
...
});
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(NavBar));
/nav_bar.jsx
import React from 'react';
import { Link, withRouter } from 'react-router-dom';
import NavBarSearch from './nav_bar_search';
const NavBar = (props) => {
return (
<div>
< NavBarSearch
fetchSearchedUsers={props.fetchSearchedUsers}
searchResults={props.searchResults}
/>
</div>
);
};
export default withRouter(NavBar);
/nav_bar_search.jsx
import React from 'react';
import NavBarSearchResults from './nav_bar_search_results';
import { withRouter } from 'react-router-dom';
class NavBarSearch extends React.Component {
constructor(props) {
super(props);
this.state = {
searchInput: ''
}
this.generateSearch = this.generateSearch.bind(this)
}
render() {
return (
<div >
<input className="search-bar-test" onChange={this.generateSearch} type="text" placeholder='Search' />
{this.state.searchInput ? <NavBarSearchResults
searchResults={this.props.searchResults}
handleClick={this.handleClick}
// key={this.props.searchResults.id}
/> : null
}
</div>
)
}
}
export default withRouter(NavBarSearch);
/nav_bar_search_results.jsx
import React from 'react';
import { withRouter, Link } from 'react-router-dom';
const NavBarSearchResults = function({ searchResults, handleClick }) {
let results = searchResults ? Object.entries(searchResults).map((result) =>
<Link className="search-links" to={`/users/${result[0]}`} onClick={e => handleClick} key={result[0]}>
<div className="search-results-item">
<img className="search-results-image" src={result[1].photoUrl} />
{result[1].username}
</div>
</Link>
) : null
return (
<div className="search-results-container">
{results}
</div>
);
}
export default withRouter(NavBarSearchResults);
Once again, it is the Link in the Nav_Bar_Search_Results.jsx file that is not working. This file is nested several levels deep starting from the Greeting.jsx file. The string interpolation I'm doing is the user_id number. Please recall that the url parameters updates and the page works if I CLICK and REFRESH page, but not on first click alone.
The correct user page should render as specified by the url parameters

React Router + Redux: history is undefined

I have the following component:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { logoutUser } from '../actions';
class NavBar extends Component {
onLogoutClick() {
this.props.logoutUser();
this.props.history.push('/login'); // here is the issue
}
render() {
return (
<div>
<button
className="btn btn-danger pull-xs-right"
onClick={this.onLogoutClick.bind(this)}
>
Logout
</button>
</div>
);
}
}
export default connect(null, {logoutUser})(NavBar);
I get this error in the console:
Cannot read property 'push' of undefined
Why doesn't this component have history in its props ?
Update 1
This is my App.js which hosts BrowserRouter:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import promise from 'redux-promise';
import reducers from './reducers';
import LoginForm from './components/login_form';
import NavBar from './components/nav_bar';
import Homepage from './components/home_page';
import PrivateRoute from './components/private_route';
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<div>
<PrivateRoute exact path="/" component={Homepage} />
<Route exact path="/login" component={LoginForm} />
</div>
</BrowserRouter>
</Provider>
, document.querySelector('.container'));
and this is the PrivateRoute:
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import Homepage from './home_page';
export const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
<Component {...props} />
props.location } }} />
)} />
)
export default PrivateRoute;
and Homepage.js:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import NavBar from './nav_bar';
export default class HomePage extends Component {
render() {
return (
<div>
<NavBar />
<h1>Welcome to the homepage</h1>
</div>
);
}
}
Update 2
I also have LoginForm component which is more or less the same as the previous component, but it works fine:
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import { loginUser } from '../actions';
import validator from 'validator';
class LoginForm extends Component {
renderField(field) {
//....
}
onSubmit(values) {
this.props.loginUser(values, () => {
this.props.history.push('/');
});
}
render() {
const {handleSubmit} = this.props;
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<Field
name="username"
label="Username"
component={this.renderField}
/>
<Field
name="password"
label="Password"
component={this.renderField}
/>
<button type="submit" className="btn btn-primary">Enter</button>
</form>
);
}
}
function validate(values) {
const errors = {};
return errors;
}
export default reduxForm({
validate,
form:'LoginForm'
})(
connect(null, { loginUser })(LoginForm)
);
You need to decorate your component with withRouter
eg. add to the top:
import { withRouter } from 'react-router';
and change your export to:
export default withRouter(connect(null, {logoutUser})(NavBar));
This will give you the react router props.
See https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/withRouter.md

Resources