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

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.

Related

Why don't Framer Motion pages load after using the menu?

I'm using framer-motion with react to make transitions between my pages, but I have an issue with one transition.
When I'm in the homepage, scroll a bit and click on the menu to go to other page, the next page is empty. In fact by looking in the inspector I can see that the previous page (home) is still in the DOM (+ the new one) and did not exit.
video of the bug : https://www.awesomescreenshot.com/video/11523168
Here's my home component :
import React, {useState, useEffect, useContext} from 'react'
import FirstSection from './FirstSection/FirstSection';
import StickyNav from './FirstSection/StickyNav/StickyNav';
import SndSection from "../sections/Content2/SndSection.js"
import './Home.css';
import LeftOne from "../sections/FirstSection/LeftOne.js";
import ThirdSection from './Content3/ThirdSection';
import { slideContext } from '../../App';
import { motion } from 'framer-motion';
export default function Home() {
const context = useContext(slideContext);
const [scroll, setScroll] = useState();
useEffect(() => {
const handleScroll = event => {
setScroll(window.scrollY);
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return (
<motion.div
id={context.end ? "end-transition" : ""}
className='home'
initial={{width:0, opacity:0}}
animate={{width:'100%', opacity:1}}
exit={{x:window.innerWidth, transition:{duration: 0.3}, opacity:0}}
>
{scroll >= 100 ? <StickyNav /> : ""}
<div id="page">
<LeftOne element='v1'/>
<div id="ctn">
<FirstSection />
<SndSection />
<ThirdSection />
</div>
</div>
</motion.div>
)
}
App.js :
return (
<HashRouter>
<slideContext.Provider value={{end, setEnd, endInscr, setEndInscr, number, setNumber}}>
<div className="App">
<AnimatedRoutes />
</div>
</slideContext.Provider>
</HashRouter>
);
AnimatedRoutes :
import React from 'react'
import {Routes, Route, useLocation} from "react-router-dom";
import AboutUs from './AboutUs/AboutUs';
import Error from './Error';
import Inscription from './Inscription/Inscription';
import Thanks from './Inscription/Thanks';
import Privacy from './Privacy/Privacy';
import Home from './sections/Home';
import Terms from './Terms&Conditions/Terms';
import {AnimatePresence} from 'framer-motion';
export default function AnimatedRoutes() {
const location = useLocation();
return (
<AnimatePresence>
<Routes location={location} key={location.pathname}>
<Route path='/' element={<Home />} />
<Route path='/register' element = {<Inscription />} />
<Route path='/thanks-registration' element ={<Thanks />} />
<Route path='/aboutUs' element={<AboutUs />}/>
<Route path='/termsAndConditions' element={<Terms />} />
<Route path="/privacy" element={<Privacy />}/>
<Route path="/error" element={<Error />} />
</Routes>
</AnimatePresence>
)
}

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 LocalStorage item

I want to do a type of authorization in react, but I ran into a problem when I add a token in one component, the 2nd does not see it, but sees it only after reloading the application.
How can this be corrected in the react?
import React from 'react';
import {NavLink} from "react-router-dom";
const Login = () => {
const handleLogin = () => {
console.log( localStorage.getItem('token'));
localStorage.setItem('token', 'token');
}
return (
<div>
<header className="">
<ul>
<li><NavLink to="/main" activeClassName={'active-link'}>Home</NavLink></li>
</ul>
</header>
<button onClick={handleLogin}>login</button>
</div>
);
};
export default Login;
App.js
import './App.css';
import React from 'react';
import {Route,Redirect,Switch} from 'react-router-dom'
import Login from "./pages/login";
import Logout from "./pages/logout";
import Main from "./pages/main";
import ErrorPage from "./pages/error";
function App() {
return (
<div className="App">
<div>ore</div>
<Switch>
<Route exact path="/">
<Redirect to="/login" />
</Route>
{
localStorage.getItem('token') ? <Route path="/main" component={Main} /> : null
}
<Route path="/login" component={Login} />
<Route path="/portfolio" component={Logout} />
<Route path="/error" exact component={ErrorPage} />
<Redirect to={'/error'} />
</Switch>
</div>
);
}
export default App;
you can use the useEffect and useState into your app.js
const [token, setToken] = useState([]);
const tokenFromLogin = localStorage.getItem("token");
useEffect(() => {
setToken(tokenFromLogin);
}, [jwt]);

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

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.

react-router-dom Redirect causes : Maximum update depth exceeded

I am attempting to redirect from the root url of my app and I get the above error. I have read some of the other answers here on SO that reference this error but they center on state being updated cyclically and I can't see where I'm doing it in the Router:
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter as Router, Route, Switch, Redirect} from 'react-router-dom'
import BookDetails from './BookDetails'
import NavBar from './NavBar'
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<>
<Router>
<NavBar/>
<Switch>
<Redirect from="/" to="/search" component={App} /> {/** */}
<Route path="/search" component={App} />
<Route path="/" component={App} />
</Switch>
<Route path="/book/:bookId" component={BookDetails} />
</Router>
</>
, document.getElementById('root'));
Or in the App.js file which I hope is okay :
import React, {useState, useEffect} from 'react'
import {Link} from 'react-router-dom'
// import debounce from 'lodash'
import noimage from './noimage.png'
import axios from 'axios'
import './App.css';
const App = (props) =>{
const [books,setBooks] = useState([])
const [isLoading,setIsLoading] = useState(false)
const [hasError,setHasError] = useState(false)
const [searchTerm,setSearchTerm] = useState('')
console.log("props",(props.history.location.pathname))
const input = str => {
console.log(str)
setSearchTerm(str)
getData(str)
}
const getData = async () => {
if(searchTerm && searchTerm.length >= 2){
if(isLoading === false)setIsLoading(true)
let s = `http://localhost:7000/books/search/${searchTerm}`
await axios.get(s)
.then(resp => {
console.log(resp.data.books)
if(books === [])setBooks([...resp.data.books])
//props.history.push(s)
})
.catch(error => {
console.log(error)
setHasError(true)
setIsLoading(false)
})
}
if(isLoading === true) setIsLoading(false)
}
const img = {
height : "175px",
width : "175px"
}
// useEffect(() =>{
// setTimeout(() => getData(),2250)
// },[])
return isLoading ? (
<div className="App">
<div className="spinner"></div>
<div className="App loading">
<p><i>loading...</i></p>
</div>
</div>
)
: hasError ? (
<div className="App loading-error">
⚠ There is a network issue: Please try again later
</div>
)
:
(
<div className="App">
<div className="search">
<div className="container">
<div className="content">
<input
type="search"
placeholder="Search..."
aria-label="Search"
className="search-form"
value={searchTerm}
onChange={e => input(e.target.value)}
/>
</div>
</div>
</div>
{
(books && books.length >= 1) &&
books.map((b,i) => {
console.log(typeof b.imageLinks)
return (
<div key={`${b.title}-${i}`} className="search-book">
<Link to={`/book/${b.id}`}>
{
(b.imageLinks === undefined || b === undefined || b.imageLinks.thumbnail === undefined) ?
<img src={noimage} alt ="Missing" style={img}></img>
:
<img src={b.imageLinks.thumbnail} alt={b.title}></img>
}
</Link>
<p>{b.title}</p>
<hr/>
</div>
)}
)
}
</div>
)
}
export default App;
I can't demo the code since it involves a REST Api server that's local to my machine. Thanks.
Well my instructor suggested this : https://reacttraining.com/react-router/web/api/Switch
and I thought I tried this already but I read the docs and tried this -
(
<Router>
<NavBar/>
<Switch>
<Redirect exact from="/" to="/search" component={App} />
<Route path="/search" component={App} />
<Route path="/book/:bookId" component={BookDetails} />
</Switch>
</Router>
)
The exact property isn't needed on all the routes. But I thank Kishan for his effort, he definitely was on the right track. Thanks again.
<>
<Router>
<NavBar/>
<Switch>
<Redirect from="/" to="/search" component={App} /> {/** */}
<Route exact path="/search" component={App} />
<Route exact path="/book/:bookId" component={BookDetails} />
</Switch>
</Router>
</>
try this way, maybe helps you

Categories