ReactJS Error: Element type is invalid: expected a string (for built-in components) - javascript

I am trying to export class and import it in another file, but I kept getting this error: ...
Check the render method of NewsfeedDetail.
I want to export component from this file: NewsfeedDetail.js
import React from "react";
import {
Card,
Container,
Dimmer,
Header,
Image,
Loader,
Message,
Segment,
} from "semantic-ui-react";
import { articleDetailURL, } from "../constants";
import axios from "axios";
class NewsfeedDetail extends React.Component {
state = {
loading: false,
error: null,
data: [],
};
componentDidMount() {
this.handleFetchItem();
};
handleFetchItem = () => {
const {
match: { params }
} = this.props;
this.setState({ loading: true });
axios
.get(articleDetailURL(params.articleID))
.then(res => {
this.setState({ data: res.data, loading: false });
})
.catch(err => {
this.setState({ error: err, loading: false });
});
};
render() {
const { data, error, loading } = this.state;
const item = data;
return (
<Container>
{error && (
<Message
error
header="There was some errors with your submission"
content={JSON.stringify(error)}
/>
)}
{loading && (
<Segment>
<Dimmer active inverted>
<Loader inverted>Loading</Loader>
</Dimmer>
<Image src="/images/wireframe/short-paragraph.png" />
</Segment>
)}
<Header as='h4' textAlign='center'>
<Header.Content>
{item.title}
</Header.Content>
</Header>
<Card>
<Card.Content>
<Card.Category >
{item.category}
</Card.Category>
<Card.Description>
{item.description}
</Card.Description>
<Card.Body>
{item.body}
</Card.Body>
</Card.Content>
</Card>
</Container>
);
}
};
export default NewsfeedDetail;
And I want to import it in this file: routes.js
import React from "react";
import { Route } from "react-router-dom";
import Hoc from "./hoc/hoc";
import Login from "./containers/Login";
import Signup from "./containers/Signup";
import HomepageLayout from "./containers/Home";
import ProductList from "./containers/ProductList";
import ProductDetail from "./containers/ProductDetail";
import OrderSummary from "./containers/OrderSummary";
import Checkout from "./containers/Checkout";
import Profile from "./containers/Profile";
import AboutLayout from "./containers/About";
import HotelLayout from "./containers/Hotel";
import NewsfeedList from "./containers/NewsfeedList";
import NewsfeedDetail from "./containers/NewsfeedDetail";
const BaseRouter = () => (
<Hoc>
<Route exact path="/products" component={ProductList} />
<Route path="/products/:productID" component={ProductDetail} />
<Route path="/login" component={Login} />
<Route path="/signup" component={Signup} />
<Route path="/order-summary" component={OrderSummary} />
<Route path="/checkout" component={Checkout} />
<Route path="/profile" component={Profile} />
<Route exact path="/" component={HomepageLayout} />
<Route exact path="/about" component={AboutLayout} />
<Route exact path="/hotel" component={HotelLayout} />
<Route exact path="/articles" component={NewsfeedList} />
<Route path="/articles/:articleID" component={NewsfeedDetail} />
</Hoc>
);
export default BaseRouter;
I have tried exporting with no default, and use {} when importing but it does not work either.
Please help me.

Related

Redirect is not changing the url in react app

My render page
import "./splash.css";
import { Redirect } from 'react-router-dom';
import React from 'react';
function Splash() {
const login = () => {
console.log('123')
return <Redirect to='/login' />;
}
const signup = () => {
return <Redirect to='/sign-up' />;
}
return (
<>
<div className="bannerContainer">
<h1>Costco Connect</h1>
</div>
<div className="formContainer">
<div
className="loginContainer"
onClick={login}
>
<h2>Login</h2>
</div>
<div
className="loginContainer"
onClick={signup}
>
<h2>Sign Up</h2>
</div>
</div>
</>
);
}
export default Splash;
And my app.js
import React, { useState, useEffect } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import SignUpForm from './components/auth/SignUpForm';
import NavBar from './components/NavBar';
import ProtectedRoute from './components/auth/ProtectedRoute';
import UsersList from './components/UsersList';
import User from './components/User';
import { authenticate } from './store/session';
import Tickets from './components/Tickets';
import Departments from './components/Departments';
import Splash from './components/Splash';
import LoginForm from './components/auth/LoginForm';
function App() {
const [loaded, setLoaded] = useState(false);
const dispatch = useDispatch();
useEffect(() => {
(async () => {
await dispatch(authenticate());
setLoaded(true);
})();
}, [dispatch]);
if (!loaded) {
return null;
}
return (
<BrowserRouter>
<ProtectedRoute >
<NavBar />
</ProtectedRoute>
<Switch>
<Route path='/login' exact={true}>
<LoginForm />
</Route>
<Route path='/sign-up' exact={true}>
<SignUpForm />
</Route>
<ProtectedRoute path='/users' exact={true} >
<UsersList />
</ProtectedRoute>
<ProtectedRoute path='/users/:userId' exact={true} >
<User />
</ProtectedRoute>
<Route path='/' exact={true} >
<Splash />
</Route>
<ProtectedRoute path='/departments' exact={true} >
<Departments />
</ProtectedRoute>
<ProtectedRoute path='/departments/:departmentId/tickets' exact={true} >
<Tickets />
</ProtectedRoute>
{/*
<ProtectedRoute path='/departments/:departmentId/tickets/:ticketId' exact={true} >
<Tickets />
</ProtectedRoute> */}
</Switch>
</BrowserRouter>
);
}
export default App;
Basically I'm trying to make it when you click on a div it will send you to the relevant form to either sign up or log in but I cannot figure out why the url isn't being redirected. If I throw a console.log inside of the functions they are running so I'm convinced the bug is in my app.js somewhere but I've run out of things to try. Thanks in advance, I've looked at other similar posts but no solutions have helped so far.
The solution was to use a NavLink instead, the Redirects were only working if they were inside a conditional and then returning.

react cannot call a class as a function

I'm only using functional components in my project and despite that, I'm getting this error: Uncaught TypeError: Cannot call a class as a function.
This is part of the parent component where I get the error:
(the problem is with the "withCheckCountry" component)
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/reset-password/:token" component={RestPass} />
<Route path="/programs" component={About} />
<Route path="/login" component={Login}>
{loggedIn() && <Redirect to={redirectionPath()} />}
</Route>
<Route path="/signUp" component={SignUp}>
{loggedIn() && <Redirect to={redirectionPath()} />}
</Route>
<Route
path="/country/:countryCode"
component={withCheckCountry(CountryApp, availableCountry, loadingCountry)}
/>
<Redirect to="/" />
</Switch>
and here is the "withCheckCountry" component:
import React, {useState, useEffect, memo} from 'react';
import PropTypes from 'prop-types';
import { Redirect } from 'react-router-dom';
import { toast } from 'react-toastify';
import ToastBody from "components/toastBody/toast";
import { FormattedMessage, injectIntl } from "react-intl";
const withCheckCountry = (Component, availableCountry, loadingCountry) => ({
...props
}) => {
//console.log("props = "+JSON.stringify(props));
if (!loadingCountry) {
const { countryCode } = props.match.params;
const isCountryExist = availableCountry.some(
country => country.countryCode === countryCode.toLocaleUpperCase(),
);
const [errorTitle, setErrorTitle] = useState(intl.formatMessage(messages.errorTitle));
const [countryNotExist, setCountryNotExist] = useState(intl.formatMessage(messages.countryNotExist));
useEffect(() => {
setErrorTitle(intl.formatMessage(messages.errorTitle));
setCountryNotExist(intl.formatMessage(messages.countryNotExist));
}, [intl]);
if (!isCountryExist) {
toast(() => <ToastBody title={errorTitle} message={countryNotExist} />);
return <Redirect to="/" />;
}
}
return <Component {...props} />;
};
withCheckCountry.propTypes = {
availableCountry: PropTypes.object,
};
export default injectIntl(withCheckCountry);
this error didn't show up until I added "injectIntl" when exporting the component, and I need that to get intl from props as you can see in the documentation here if you are interested.
you are calling "withCheckCountry" component as if it was a function:
try this:
<Route path="/country/:countryCode" component={(props) => <withCheckCountry {...props} />} />

Pagination in react not working. Adds in extra to the URL string once loaded

hi hope someone can help me. I have added pagination into my react app. I have checked and the query strings are working as they should be on the back end. However when I try and click through the pagination buttons it adds extra to the URL so instead of localhost:3000/topic/page/1 it is localhost:3000/topic/page/topic/page/1. Therefore I get a not found error when I click on the link.
Routes file
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import Register from '../auth/Register';
import Login from '../auth/Login';
import Alert from '../layout/Alert';
import Dashboard from '../dashboard/Dashboard';
import CreateProfile from '../profile-forms/CreateProfile';
import EditProfile from '../profile-forms/EditProfile';
import Profiles from '../profiles/Profiles';
import Profile from '../profile/Profile';
import Posts from '../posts/Posts';
import Post from '../post/Post';
import Topics from '../topic/Topics';
import Flashcard from '../flashcard/Flashcard';
import Quiz from '../quiz/Quiz';
import Factsheet from '../factsheet/Factsheet';
import NotFound from '../layout/NotFound';
import PrivateRoute from '../routing/PrivateRoute';
const Routes = () => {
return (
<section className="container">
<Alert />
<Switch>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<PrivateRoute exact path="/profiles" component={Profiles} />
<PrivateRoute exact path="/profile/:id" component={Profile} />
<PrivateRoute exact path="/dashboard" component={Dashboard} />
<PrivateRoute exact path='/create-profile' component={CreateProfile} />
<PrivateRoute exact path='/edit-profile' component={EditProfile} />
<PrivateRoute exact path='/topic' component={Topics} />
<PrivateRoute exact path='/topic/search/:keyword' component={Topics} />
<PrivateRoute exact path='/topic/page/:pageNumber' component={Topics} />
<PrivateRoute exact path='/topic/search/:keyword/page/:pageNumber' component={Topics} />
<PrivateRoute exact path='/topic/flashcard/:id' component={Flashcard} />
<PrivateRoute exact path='/topic/quiz/:id' component={Quiz} />
<PrivateRoute exact path='/topic/factsheet/:id' component={Factsheet} />
<PrivateRoute exact path="/posts" component={Posts} />
<PrivateRoute exact path="/posts/:id" component={Post} />
<Route component={NotFound} />
</Switch>
</section>
);
};
export default Routes;
Paginate.js
import React from 'react'
import { Pagination } from 'react-bootstrap'
import { Link } from 'react-router-dom';
import { LinkContainer } from 'react-router-bootstrap'
const Paginate = ({ pages, page, keyword = '' }) => {
return (
pages > 1 && (
<Pagination>
{[...Array(pages).keys()].map((x) => (
<LinkContainer
tag={Link}
key={x + 1}
to={keyword
? `topic/search/${keyword}/page/${x + 1}`
: `topic/page/${x + 1}`
}
>
<Pagination.Item active={x + 1 === page}>{x + 1}</Pagination.Item>
</LinkContainer>
))}
</Pagination>
)
)
}
export default Paginate
SearchBox.js
import React, { useState } from 'react'
import { Form, Button } from 'react-bootstrap'
const SearchBox = ({ history }) => {
const [keyword, setKeyword] = useState('')
const submitHandler = (e) => {
e.preventDefault()
if(keyword.trim()) {
history.push(`/topic/search/${keyword}`)
} else {
history.push('/topic')
}
}
return (
<Form onSubmit={submitHandler} inline>
<Form.Control
type="text"
name="q"
onChange={(e) => setKeyword(e.target.value)}
placeholder="Search Topics....."
></Form.Control>
</Form>
)
}
export default SearchBox
topic.js
import React, { Fragment, useEffect } from 'react';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Spinner from '../layout/Spinner';
import Paginate from '../layout/Paginate'
import TopicItem from './TopicItem';
import { getTopics } from '../../actions/topic';
const Topics = ({ getTopics, topic: { topics, loading, pages, page }, match }) => {
const keyword = match.params.keyword
const pageNumber = match.params.pageNumber || 1
useEffect(() => {
getTopics(keyword, pageNumber);
}, [getTopics, keyword, pageNumber])
return (
<Fragment>
{loading ? (
<Spinner />
) : (
<Fragment>
<h1 className="large text-primary1 my-2">Pick a Topic</h1>
<Link to="/topic" className="btn my-4">
Back To Topics
</Link>
<div className="card-grid-home">
{topics.length > 0 ? (
topics.map(topic => (
<TopicItem key={topic._id} topic={topic} />
))
) : (
<h4>No topics found......</h4>
)}
</div>
<Paginate pages={pages} page={page} keyword={keyword ? keyword : ''}/>
</Fragment>
)}
</Fragment>
)
};
Topics.prototype = {
getTopics: PropTypes.func.isRequired,
topic: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
topic: state.topic
})
export default connect(mapStateToProps, { getTopics })(Topics)
Thanks in advance
Realised that I was missing a / for the start of the routes. Silly mistake.

How can I pass in props from App.js to my login component?

I'm new to React. I'm having trouble with getting React to recognize a prop passed in from App.js to the Login component. Specifically what I'm trying to do is getting React to do two things: 1. To check if a user is logged in. 2. What user is currently logged in. I'm using Passport, passport-local, Mongoose, MongoDB, Axios, Express, and react-router-dom to make this happen. When I attempt to log in a user I created in the database I get the following in the console:
TypeError: "this.props.updateUser is not a function"
onSubmit login.component.js:42
App.js:
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import axios from "axios";
/* Begin Import Components */
import NavigationBar from "./components/navbar.component";
import MainLanding from "./components/main-landing.component";
import Contact from "./components/general-components/contact.component";
import Register from "./components/general-components/register.component";
import Login from "./components/general-components/login.component";
import ProductsList from "./components/product-components/products-list.component";
import ProductDetails from "./components/product-components/product-details.component";
import ProductCreate from "./components/product-components/product-create.component";
import ProductEdit from "./components/product-components/product-edit.component";
import ProductDelete from "./components/product-components/product-delete.component";
import UsersList from "./components/user-components/users-list.component";
import UserDetails from "./components/user-components/user-details.component";
import OrdersList from "./components/order-components/orders-list.component";
import OrderDetails from "./components/order-components/order-details.component";
import OrderCreate from "./components/order-components/order-create.component";
import OrderEdit from "./components/order-components/order-edit.component";
/* End Import Components */
class App extends Component {
constructor(props) {
super(props);
this.state = {
loggedIn: false,
user: {}
}
this.getUser = this.getUser.bind(this);
this.componentDidMount = this.componentDidMount.bind(this);
this.updateUser = this.updateUser.bind(this)
}
getUser() {
axios.get('http://localhost:4000/logged_in').then(response => {
console.log('Get user response: ')
console.log(response.data)
if (response.data.user) {
this.setState({
loggedIn: true,
user: response.data.user
})
} else {
console.log('Get user: no user');
this.setState({
loggedIn: false,
user: {}
})
}
})
}
componentDidMount() {
this.getUser();
}
updateUser(userObject) {
this.setState(userObject)
}
render() {
return (
<Router>
<NavigationBar />
<div className="container">
{/* Begin Routes. Begin General Routes */}
<Route path="/" exact component={MainLanding} />
<Route path="/contact" exact component={Contact} />
<Route path="/register" exact component={Register} />
<Route path='/login' render={(props) => <Login {...props} />}/>
{/* End General Routes. Begin Products Routes */}
<Switch>
<Route path="/products/" exact component={ProductsList} />
<Route path="/products/new" exact component={ProductCreate} />
<Route path="/products/:id" exact component={ProductDetails} />
<Route path="/products/:id/edit" exact component={ProductEdit} />
<Route path="/products/:id/delete" exact component={ProductDelete} />
</Switch>
{/* End Products Routes. Begin Users Routes */}
<Switch>
<Route path="/users/" exact component={UsersList} />
<Route path="/users/:id" exact component={UserDetails} />
</Switch>
{/* End Users Routes. Begin Orders Routes */}
<Switch>
<Route path="/orders/" exact component={OrdersList} />
<Route path="/orders/new" exact component={OrderCreate} />
<Route path="/orders/:id" exact component={OrderDetails} />
<Route path="/orders/:id/edit" exact component={OrderEdit} />
</Switch>
{/* End Orders Routes. End Routes */}
</div>
</Router>
);
}
}
export default App;
Login Component:
import React, { Component } from "react";
import { Col, Form, Button } from "react-bootstrap";
import axios from "axios";
class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: ""
}
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onchangePassword = this.onchangePassword.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
onchangePassword(e) {
this.setState({
password: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
axios.post("http://localhost:4000/login", {
username: this.state.username,
password: this.state.password
}).then(res => {
console.log(res)
if (res.status === 200) {
this.props.updateUser({
loggedIn: true,
username: res.data.username
})
}
}).catch(error => {
console.log(error);
});
this.setState({
username: "",
password: ""
})
this.props.history.push("/");
}
render() {
return (
<div className="text-center">
<h2>Login</h2>
<Form onSubmit={this.onSubmit}>
<Form.Row>
<Form.Group as={Col} sm={{ span: 6 }}>
<Form.Label htmlFor="formUsername">Username</Form.Label>
<Form.Control
controlid="formUsername"
type="text"
value={this.state.username}
onChange={this.onChangeUsername}
placeholder="Enter username"
/>
</Form.Group>
<Form.Group as={Col} sm={{ span: 6 }}>
<Form.Label htmlFor="formPassword">Password</Form.Label>
<Form.Control
controlid="formPassword"
type="password"
value={this.state.password}
onChange={this.onchangePassword}
placeholder="Enter password"
/>
</Form.Group>
</Form.Row>
<Button variant="success" type="submit">
Login
</Button>
</Form>
</div>
)
}
}
export default Login;
Let me know if I need to provide any additional information. Thank you.
The function updateUser() is defined correctly but you need to pass it to the Login component:
App.js
<Route path='/login' render={(props) =>
<Login {...props} updateUser={this.updateUser} />
}/>
This will append props.updateUser to the Login component on top of all the props from the parent component (App.js).
It does seem to be that you still not put updateUser as props of Login component. You could try like this
<Route path='/login' render={(props) =>
<Login {...props} updateUser={this.updateUser} />
}/>
But, i think that this.props.updateUser() may also be come from redux of application (mapDispatchtoProps). If so, you just connect Login component to redux, don't need to put this function as props in Login component.

multiple page in react router v4

I am using react router v4 for routing. The layout my app is, there is homepage which is for end user. The path for homepage is obviously /. There is dashboard section too. One for admin, one for agent and another for owner. They have their own layout from top to bottom. For homepage its working. But when i hit url /admin/dashboard, the main page of admin dasboard is not shown. The same homepage is shown.
Here is what i have done
const AsyncRoute = ({ load, ...others }) => (
<Route
{...others} render={(props) => (
<Bundle load={load} {...props} />
)}
/>
);
app.js
const render = messages => {
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
document.getElementById("app")
);
};
import Routes from 'routes';
class App extends React.Component {
render() {
return (
<div>
<Navbar userForm={this.handleDialog} />
<Routes />
</div>
);
}
}
routes.js
function Routes({ location }) {
return (
<Switch location={location}>
<AsyncRoute exact path="/" load={loadHomePage} />
<AsyncRoute exact path="/features" load={loadFeaturePage} />
<AsyncRoute path="" load={loadNotFoundPage} />
</Switch>
);
}
I want now admin dashboard a complete new page with different layout not children of App component so i did
the following
class AdminDashboard extends React.Component {
render() {
return (
<div>
<TopNavigation />
<SideNavigation />{/* it will have link */}
<Routes /> {/* it will display page */}
</div>
);
}
}
function AdminRoutes({ location }) {
return (
<Switch location={location}>
<AsyncRoute
exact
path="/admin/dashboard"
load={loadAdminDashboardPage}
/>
<AsyncRoute exact path="/commission" load={loadCommissionPage} />
<AsyncRoute path="" load={loadNotFoundPage} />
</Switch>
);
}
when i hit the url /admin/dashboard i get the app page not the admin dashboard page and same with the
/commission which should be a child of AdminDashboard
How can i make my router work for different layout?
From Meteorchef Base, dedicated routing according to the user (loggingIn prop in this case):
Public.js, only for non admin, redirect if not :
import React from 'react';
import PropTypes from 'prop-types';
import { Route, Redirect } from 'react-router-dom';
const Public = ({ loggingIn, authenticated, component, ...rest }) => (
<Route {...rest} render={(props) => {
if (loggingIn) return <div></div>;
return !authenticated ?
(React.createElement(component, { ...props, loggingIn, authenticated })) :
(<Redirect to="/account" />);
}} />
);
Public.propTypes = {
loggingIn: PropTypes.bool,
authenticated: PropTypes.bool,
component: PropTypes.func,
};
export default Public;
Authenticated.js, only for admin, also redirect if not :
import React from 'react';
import PropTypes from 'prop-types';
import { Route, Redirect } from 'react-router-dom';
const Authenticated = ({ loggingIn, authenticated, component, ...rest }) => (
<Route {...rest} render={(props) => {
if (loggingIn) return <div></div>;
return authenticated ?
(React.createElement(component, { ...props, loggingIn, authenticated })) :
(<Redirect to="/login" />);
}} />
);
Authenticated.propTypes = {
loggingIn: PropTypes.bool,
authenticated: PropTypes.bool,
component: PropTypes.func,
};
export default Authenticated;
then in your App, (stateless in this case, but you can create a class as well too) :
// import everything
const App = appProps => (
<Router>
<div>
<Switch>
<Route exact name="index" path="/" component={Home} />
<Authenticated exact path="/account" component={Account} {...appProps} />
<Public path="/signup" component={Signup} {...appProps} />
<Public path="/login" component={Login} {...appProps} />
<Route component={NotFound} />
</Switch>
</div>
</Router>
);
App.propTypes = {
loggingIn: PropTypes.bool,
authenticated: PropTypes.bool,
};

Categories