React doesn't render on page refresh or manual URL entry - reactjs

I've made two components. one is Articles.js and the another one is article.js. The router is in app.js. here is code from app.js:
<Router>
<Switch>
<Route exact path="/articles" component={Articles}>
</Route>
<Route path="/article/:id" component={Article}/>
</Switch>
</Router>
I've made link to "article/:id" in Articles component. If I click on the link in articles page, it works just fine, however, If I try to reload the page or manually enter id, for eg: "article/23", it will not render anything at all on the page.
I found some results on internet, but, most of them are either not relevant or are using hooks, which I cannot use with class components.
In componentDidMount function of Article compnent i am calling getData function which fetches data from the server and then after verfiying the response sends data here to this function :
initFunction = (ar)=>{
let data = ar.map(d=>{
return(
<tr><td>{d.id}</td><td>{d.title}</td><td>{moment(d.created_on).format('MMMM,Do YYYY')}</td><td>
<Link to={`article/${d.id}`}>Edit</Link> |
<Link to={`article/delete/${d.id}`}> Delete</Link>
</td></tr>
)
})
this.setState({
tableData:<>{data}</>
})
}
And this function just generates table rows and save them in state, which I use in render function to display the data. If I go to article page through this link, it will work fine but same link will not render anything if type it manually or reload it.
Here are the components I am importing in my component:
import ReactPaginate from 'react-paginate';
import { Link } from 'react-router-dom';
import { instanceOf } from 'prop-types';
import { withCookies, Cookies } from 'react-cookie';
import moment from 'moment'

The issue here is probably that your server is not set up to serve your app on the /article route.
When you click on the link in your app then react-router does not actually request make a request to your server for that route. Instead it updates the url and re-renders your app which picks up the new route.
When you load the route directly (such as on page reload or manually typing in the url bar) the react router has not been loaded yet. Instead the browser just blindly makes a request to that route. This is when your app is failing.

I had the same issue as you. I found the solution from this thread.
react-router dynamic segments crash when accessed
added into the of my index.html

what is initState of id, I think you need to store id to state and set initState is empty string, it work for me.
const [myId, setMyId] = useState("")

Related

Navigation links server side rendering in nextjs

i'm still new to nextjs and i'm building static site, i'm trying to make server responsible for rendering navigation links but i can't figure this yet how to do this and how to fetch those links
as you know navigation links lies in seperate component and not included in every page and also fetching data must be in nextPage not in the components
the only solution i have is to fetch navigation links when home page loads and then get the navigation links as props and pass it the context but this will make the client responsible for rendering the naviagtion
my _app.js is
import '../styles/globals.scss'
import { Layout } from '../components'
function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
export default MyApp
as you see the Layout contains the navigation and Component has the rest
The global data should come from the layout, not from the page. If you have more than one page, you don't want to repeat your API calls in each pages.
If you use the nextjs 13 (still in beta atm), you can do this in the app/ directory. If you don't, you will need to use useSwr in your layout : https://nextjs.org/docs/basic-features/layouts.
To summarize, if you really want to be client agnostic on this feature, i think you need to try nextjs 13.

How to fix slow page changing speed to heavy routes with React Router?

I have a React project and use React Router DOM v6 to manage all my routes.
I have a route that uses a fairly heavy component and, when switching to that heavy component, there is a 1+ second delay until the current page disappears and the new one shows up, since it's taking time to render that component.
Is there a way to change pages before trying to load the component and, perhaps, show a "loading" page while it's doing that?
demo simulating the issue
By "heavy route" I meant that it renders slowly whenever you change routes to it.
What you can do is implement React.lazy() to lazy load the page and then use React.Suspense() to show a loading page while transitioning. Here is an example:
import React, { Suspense } from 'react';
// import MyPage from './pages/MyPage'
// instead of importing MyPage like above, use lazy, like below
const MyPage = React.lazy(() => import('./pages/MyPage'));
function App() {
return (
<Suspense
fallback={<div><p>Loading...</p></div>}
>
<Routes>
<Route path='/mypath' element={<MyPage} />
// other route data
</Routes>
</Suspense>
)
}
export default App;
This is a very simple example. What this does is when you initially load your page, MyPage will not be loaded. Loading of the page will be deferred until it is needed. Once you go to /mypath, MyPage will then be loaded and the Suspense component will show the loading <p> tag. Of course this can be any element you want or even a component.
Alternatively, what you could do is, inside your big component, you could use useState() to create a simple boolean isLoading and setIsLoading state and set it to true initially. Then, render a loading component if isLoading is true. After your operation is completed, set isLoading to false.

How to allow user to save inputs for further review

I have made a small calculating website and I would like the authenticated user to save his/her calculations.
Overview:
I have a main page with 8 input fields and several labels/graphs displaying results information. Whenever you change one of the inputs, the labels and graphs update thanks to hooks.
The goal: loading data
I made a "Save" button, which, when clicked :
saves all the inputs to firebase (this works fine already)
create a link in /myaccount/dashboard, which redirects you to the main page with your saved inputs (that I need help with)
I am having a hard time finding for resources online. However, while looking for responsive calculating websites, I came across this one : https://optionstrat.com
Even-thought I have no idea what they are calculating it does what I'm looking for, ie : you can "save a trade" and then go to you account where all the saved trades are displayed.
Does anyone know a good tutorial how to do so ?
Thanks you :)
Edit
This is my save function in my App.js:
function Savecalc(){
const calcRef = db.ref("User_"+auth.currentUser.uid);
const newCalc = calcRef.push();
newCalc.set({inputs:{a,b,c},outputs:{x,y}});
/* Then attribute an URL to a saved calculation*/
}
Then, in my Dashboard.js, I would have:
const db=app.database();
export default function Dashboard() {
/* getting the user calculations */
return (
<div>
<!-- Mapping of the user's calculations -->
</div>
)
I suspect what you are probably looking for is a little library called react-router-dom. This library essentially provides a collection of navigational components that you can employ to navigate around your app. Here is a basic example. Once you install it into your project, you should create a separate AppRouter.js file that might resemble something along the lines:
import React from 'react';
// Install the react-router-dom package
import { Router, Route, Switch } from 'react-router-dom';
// Further install the history package
import { createBrowserHistory } from 'history';
// Import your dashboard component and all other components you wish to create a route to
// This is just an example
import HomePage from '../components/Homepage';
import Dashboard from '../components/Dashboard';
// You will need to create a Page Not Found component that redirects when a wrong URL is inserted
import NotFoundPage from '../components/NotFoundPage';
export const history = createBrowserHistory();
const AppRouter = () => (
<Router history={history}>
<Switch>
<Route path='/' component={HomePage} exact={true} />
<Route path='/myaccount/dashboard' component={Dashboard} />
<Route component={NotFoundPage} />
</Switch>
</Router>
);
export default AppRouter;
Then in your main/app.js file you will need to add the AppRouter component. It should look something like this:
const Application = () => (
<Provider store={store}> // if using react-redux, otherwise ignore Provider
<AppRouter />
</Provider>
);
ReactDom.render(<Application />, document.getElementById('app'));
You can also create public and private routes (e.g. accessible only for signed in users). Examples of these can be found here.
If you are saving the user's calculations, you could then query them on whatever page you want to display them on e.g. /myaccount/dashboard.
You can then map over them and display them in the UI as links, where the link could be something like /myaccount/dashboard/YlxIJ2zOxI9KYJ5Dag6t where YlxIJ2zOxI9KYJ5Dag6t is the auto-generated document ID from Firestore.
Assuming you are using React Router, you can then have a route such as:
<Route exact path="/myaccount/dashboard/:id">
On this page, you can get the ID of the document from the parameters using React Router's useParams hook like so:
const { id } = useParams();
You can then query the specific calculation's info in useEffect, and display them however you want.
Let me know if this is what you need, or if you need more help with any step!

Is it possible to change route on scroll?

I want to load multiple components on a single page and have different routes for all of them. For example i hit a route /article/1 and it loads a component, after scrolling through completely through that article i want the route to change to /article/2 and the corresponding article to load. I am using react and react router, basically i want 4 (article/3 , article/4) articles on a page and all these should be scrollable with the route changing as i scroll onto a particular article. How can i achieve this using react and react-router?
use react-perfect-scrollbar package from npm.
index.js (main entry point of your application) add this css
import 'react-perfect-scrollbar/dist/css/styles.css';
your component file where you want on scroll change url
import PerfectScrollbar from 'react-perfect-scrollbar';
import { Redirect } from 'react-router-dom';
handleScroll = () => {
<Redirect to="/article/2" />
}
<PerfectScrollbar onYReachEnd={this.handleScroll}> // when you reach then end of screen it's call handleScroll function and redirect to other url.so based on your requirements you can pick up from here.
// your articles code..
</PerfectScrollbar>

React dynamically create routes

First things first is this possible to have 2 components on a page one displaying simple static markup but the second one in my parent is going to be a div that displays a link for each item in an array and if you click on it at the bottom of the div then data will be displayed for each one?
If this is possible are dynamic props as simple as performing .map inside the element and printing out a route?
Will also add that I am receiving the following on my Router object but I installed react-router globally though it is also in my node_modules folder.
'react-router' does not contain an export named 'hashHistory'.
import React, { Component } from 'react';
import { Router, Route, IndexRoute, hashHistory } from "react-router";
class DetailsComponent extends Component {
render() {
return (
<Router history={hashHistory}>
// in here will map this.props.data and for each one print a route
// the component for that route will be a DetailedViewComponent that
// that takes in the data in the props and renders it
// so i might need a link? in this render method aswell?
</Router>
);
}
}
export default DetailsComponent ;
React Router match params can be used to render content dynamically
ie. <Route path="/dynamicroute/:id" component={DynamicComponent}/> will provide an id param that can be retrieved via props.match.params inside <DynamicComponent/>
Spoke to some more senior react developers and they said what I was after was npm package Component-Router I haven't got back onto the project just yet but will post full code once completed :)

Resources