I have setup gatsby project and my routes only works when it contains /app because of this gatsby nodejs file.
exports.onCreatePage = async ({ page, actions }) => {
const { createPage } = actions
// page.matchPath is a special key that's used for matching pages
// only on the client.
if (page.path.match(/^\/app/)) {
page.matchPath = "/app/*"
// Update the page.
createPage(page)
}
}
I need to remove /app from my all the components. Is it possible to do so?
And also on production mode my dynamic routes does not work what is the issue?
const App = () => (
<Layout>
<Router>
<VerifyToken path="/app/:token"/>
<MagicLink path="/app/link/:magicLink"/>
</Router>
</Layout>
)
The code in your gatsby-node.js file is used to create what's called "client only routes". In the Gatsby docs they give an example that is used to create routes available only to logged-in users. These routes will exist on the client only and will not correspond to files in an app’s built assets on the server.
You could possibly eliminate the /app route if nothing is using it. But just based on the example component you posted, it does seem like your app is using it, and you did mention "dynamic routes". So you do need something to identify those routes and make them special to Gatsby.
In short, what this "client only route" is supposed to mean is that Gatsby will not create any server side pages for that route. But then you are supposed to create app components (mostly likely React components) that will respond to that route and build the content dynamically.
There is nothing special about the /app prefix. You can make it whatever you want as long as it is consistent between your Gatsby config and your client components and the router your client uses (hopefully Gastby's already built-in #reach/router?). But to create a hybrid app where some content is rendered server side by Gatsby and some content rendered dynamically client side, I'm pretty sure you need to have some kind of prefix to make that work so Gatsby can tell the difference between the two and how to render them. However, it's not clear from the Gatsby docs on page matchPath how that works. From the code example in the Gatsby docs, it does take a regular expression. It's possible that instead of /app you could try to match some other string somewhere else in the path instead of being at the beginning of the path. Whatever you do, the client side router will need to be set up to match that route too.
I don't think the Gatsby docs are that great so I can understand your struggle trying to get this to work. This Gatsby Mail App might help you to since it uses a different prefix (/threads) and has the complete source to an app that uses client side dynamic pages + static content.
And also on production mode my dynamic routes does not work what is
the issue?
Very hard to tell with the limited code you provided. That doesn't look like it's the full source to that component. Is your component named src/pages/app.js or src/pages/app/index.js? That's what it needs to be named to handle the routing for the /app prefix.
To enable client-only routes with no prefix (no /app), you setup Gatsby as below.
In gatsby-node.js:
exports.onCreatePage = ({ page, actions }) => {
const { createPage } = actions
if (page.path === `/`) {
page.matchPath = `/*`
createPage(page)
}
}
In index.js:
const IndexPage = () => {
return (
<Router>
<Home path="/" />
<OtherPage path="/other-page" />
</Router>
)
}
export default IndexPage
To remove /app from the route, you have to define your starting path named files in pages folder. For example, you want your home page to render with {your-domain}/home, just add a file named home.js in pages folder and import your component over there.
import React from "react";
import HomePage from "../features/home/Home.index";
const Home = () => (
<HomePage />
);
export default Home;
Related
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.
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("")
I have created a Single Page App with react and hosted it on netlify . I am making use of react-router to handle my routing. Is it possible to generate random routes (url) to send as a link for someone to view the current state of my app with a specific data ?
For Example:
wwww.forexample.com/myappshowing5dogs
--shows my app showing 5 dogs
wwww.forexample.com/myappshowing12catssandabook
--shows my app showing a different state of my app with 12 cats and a book
How can I generate links (url) to show all the countless possible states of my app?
You can use the useParams functionality of React-Router to do exactly that!
import {BrowserRouter, Route, useParams} from ReactRouterDOM
const Info = () => {
let {dogs, cats} = useParams();
return <div>There are {dogs || 0} dogs and {cats || 0} cats</div>;
}
const App = () => (
<BrowserRouter>
<Route path="/:dogs?/:cats?/" component={Info}/>
</BrowserRouter>)
ReactDOM.render(<App/>, document.getElementById('root'));
And to get Netlify to work nicely with these you need to add /* /index.html 200 into your _redirects file.
See my demo here:
Sourcecode shows how to do the redirects file and Routing
I'm new in Nextjs and I want to add a list of components and utilities to all of my pages in Nextjs. How can I make them all available in my components without importing them one by one.
Also some utilities might be needed in getInitialProps function in pages like axios or in my case client of Apollo.
I don't expect some one write me a whole config file for Nextjs.config just help me to understand the configuration of next deeper.
thanks in advance
I would suggest to do dynamic import on each page, for each component and utility instead of making components global. By doing so Next.js will create a small chunks or "pages" without any unused components.
If you load components globally, every page would increase in size but actually not use these components or utilities. It defeats a purpose of code-splitting.
It breaks modularity of your code, because components/pages (modules) will depend on some global utilities implicitly.
If you have too many imports in your component or page, probably, it's a sign to encapsulate that extra functionality by extracting it to it's own component.
Controversially, you could try to add global utilities in Custom "App"
For example, you could pass a React component to all Next.js pages via props of custom App.
_app.js
import Icon from '../components/Icon';
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} icon={Icon} />
}
As all pages are instancing from the App, every page would have this component in the props.
index.js
const Home = props => (
<div>
<props.icon><props.icon/>
</div>
);
If you have many components you could group them into list and assign to a single prop, so you can use it like:
index.js
const Home = props => (
<div>
<props.components.icon/>
<props.components.anotherIcon/>
</div>
);
On a side note, it's suggested to use getStaticProps and getServerSideProps for pages instead of getInitialProps since Next.js 9.3.
Suggested reading:
Next.js Data fetching (getInitialProps)
React.js Code-Splitting
I am not able to render any component on any route other than "/".
Here is my code for routes.js
import React from 'react'
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router,
Route,
} from 'react-router-dom'
import StockTable from './containers/stockTableContainer';
import StockDetail from './containers/stockDetailContainer';
export const getRoutes = (store) => {
return(
<Router>
<div>
<Route exact path ='/' component ={StockTable}/>
<Route path ='/details' component ={StockDetail}/>
</div>
</Router>
)
}
I can render the StockDetail component on "/" route but i can't route it on "/details".
I have also tried using but still couldn't render "/details"
full code at : https://github.com/shrutis18/stockApp
If your application is hosted on a static file server, you need to use a <HashRouter> instead of a <BrowserRouter>.
This is because your server doesn't know how to handle requests made to a path other than /. For the BrowserRouter to work, any routable request should be served the index.html.
An excerpt from the FAQ
When you load the root page of a website hosted on a static file
server (e.g., http://www.example.com), a <BrowserHistory> might appear
to work. However, this is only because when the browser makes the
request for the root page, the server responds with the root
index.html file.
If you load the application through the root page, in-app navigation
will work because requests are not actually made to the server. This
means that if you load http://www.example.com and click a link to
http://www.example.com/other-page/, your application will match and
render the /other-page/ route.
However, you will end up with a blank screen if you were to refresh a
non-root page (or just attempt to navigate directly to it). Opening up
your browser's developer tools, you will see an error message in the
console informing you that the page could not be loaded. This is
because static file servers rely on the requested file actually
existing.
Further along the lines
This is not an issue when your server can respond to dynamic requests. In that situation, you can instruct the server to catch all requests and serve up the same index.html file.
You can use the Switch to your route as directed in the docs
<Switch>
<Route path='some_path' component={Some component} />
</Switch>
https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/guides/basic-components.md