I'm new to react, and just pushed our app to a live environment. I've just encountered this error which stackoverflow doesnt seem to have a direct answer for, so i'm creating a new question for it.
I'm using ReactJS and NextJS 12. In my _app.js I have an array inside render():
let pagesThatDontNeedHeader = [
'RegisterNow',
'Signin',
'LoginError',
'CreateNewPassword',
];
let componentName = Component.name
if(componentName === 'WithRouterWrapper') {
componentName = Component.displayName
}
Then below when I render the page:
{pagesThatDontNeedHeader.includes(componentName) ? null : <Header />}
So now pages like Signin, Register and Create new password dont show the header, and just the form. Now, in production the names have all been minified and I have no way to compare and figure out whether the component needs a header or not.
What is the correct answer for this?
Related
i'm totally beginner in react.
I tried to improve my skill day after day.
Today im stuck on problem, i want to create dynamic route with JSON characters (here dragon ball z)
My routes are correct but i want to show biography on only clicked characters like "i click on goku show goku bio"
I want to make it without REACT HOOKS (dont useLocation, useParams ect..).
At moment i'm totally stuck
Can you help me ? how can i do?
Thanks for help :)
here is the blitzstack of my project:
REACT ROUTER DBZ EXERCICE - WITHOUT HOOKS
I don't know why you are using react-router-dom and then not really use it for what it was designed for. You are working with function components, so as far as I can tell, any solution will require a React hook. Whether you just use the useParams hook to get the id to filter by, or if you declare an id state in the parent with useState, or create a React context and use both useState and useContext, or use Redux and useDispatch and useSelector. Do you see where this is headed?
I suggest just using the useParams hook as it's the most trivial to implement.
Fix the character bio route so the id route match param is easier to read and consume.
<Route path="/CharBio/:id" element={<CharBio />} />
With path="/CharBio:id" the link would inject a leading : character into the id with to={`/CharBio${element.id}`}, i.e. instead of "goku" the id param would be ":goku", and this doesn't work easily for filtering.
Fix the link in Perso so it's linking to a "/CharBio/:id" path.
<Link to={`/CharBio/${element.id}`}>
<h1>{element.id}</h1>
</Link>
Use the useParams hook in the CharBio component and filter the API data by id.
export default function CharBio() {
const { id } = useParams();
const element = API.find(el => el.id === id);
return element ? <p>{element.bio}</p> : null;
}
This question already has answers here:
How to get previous url in react gatsby
(4 answers)
Closed 2 years ago.
Is there any way to find the path of the page that a user is on on a Gatsby site and store it in a const so that it can be checked next to the current path the user is on? In other words if they're on the /about page, and are clicking a link to navigate to the /contact page, I need to get the paths of both so that I can check them against each other. I know I can get location.pathname for the current url, but how do I find the path that they are navigating to when the click a link?
Since your code structure isn't clear. Assuming a simple anchor tag, you can do something like this:-
<a href="/new/link" onClick={getHref}>New Link</a>
And in your getHref method
function getHref(event){
console.log(event.target.href); // should log '/new/link'
}
Check if this works in your case.
Please forgive for any typo, I havent validated it.
Gatsby exposes props (because it extends from #reach/router from React) by default on the top-level components (this means pages). You can pass it to the child components as you wish or store it in a const or in a React's state.
Without knowing any page structure, I'll provide something dummy as an example:
import React from "react"
import { graphql } from "gatsby"
const YourPage = ({ location, data }) => {
console.log('your page is ', location.pathname)
return <div>Dummy content</div>
}
export default Page
export const query = graphql`
query PageQuery {
site {
siteMetadata {
siteURL
}
}
}
`
Your information is stored under props.location, that's why you can destructure it in the component's declaration.
In the case above, I've used pathname property but you have a bunch exposed. Check it out to find out which one fits your requirements.
I have setup gatsby project using this link. It is working correctly.
Now I know how to create route by defining the component inside the pages folder. But now I have a new challenge I need to create one dynamic route so that I can pass my id in it (Just like reactjs).
<Route path: "/path/:id"/>
How do I do that in gatsby?
You have to explicitly tell gatsby that a path should be dynamic. From the docs:
// gatsby-node.js
// Implement the Gatsby API “onCreatePage”. This is
// called after every page is created.
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)
}
}
and then you can use dynamic routing in src/pages/app.js
import { Router } from "#reach/router"
const SomeSubPage = props => {
return <div>Hi from SubPage with id: {props.id}</div>
}
const App = () => (
<Layout>
<Link to="/app/1">First item</Link>{" "}
<Link to="/app/2">Second item</Link>{" "}
<Router>
// ...dynamic routes here
<SomeSubPage path="/app/:id" />
</Router>
</Layout>
)
export default App
Everything that goes to /app/* will be handled dynamically now. You should find your id as usual in the props.
Have a look at their authentication example https://github.com/gatsbyjs/gatsby/tree/master/examples/simple-auth
You can use square brackets ([ ]) in the file path to mark any dynamic segments of the URL. For example, in order to edit a user, you might want a route like /user/:id to fetch the data for whatever id is passed into the URL.
src/pages/users/[id].js will generate a route like /users/:id
src/pages/users/[id]/group/[groupId].js will generate a route like /users/:id/group/:groupId
Reference: https://www.gatsbyjs.com/docs/reference/routing/file-system-route-api#creating-client-only-routes
You can use gatsby-plugin-create-client-paths. It uses matchPath. For more info check
https://www.gatsbyjs.org/docs/gatsby-internals-terminology/#matchpath
https://www.gatsbyjs.org/packages/gatsby-plugin-create-client-paths/
This answer is Super late, but for anyone in the future who is faced with this problem, I have a simpler solution.
In Gatsby terms it's called a Splat Route.
For examples, If you want some page "domain.com/profile/[id]", where id can be any number, which will be used to display different data inside the website, you should name your page as [...id].
Now inside the page you can access this id as
const ProfilePage = (props) => <div>This page is for id number {props.params.id}</div>
Note: Don't miss the 3 dots, that is what signifies a splat route in gatsby.
I’m pretty new to this so apologies in advance if I'm being dumb. I’m building a react application on top of the WordPress rest API. I’m trying to do something pretty basic which is to create a component showing a list of pages, each with a link which takes the user to a new view showing the individual ‘page’ with all the data for that page.
I’m almost there but am having problems outputting the correct data on the individual pages.
The approach I’ve taken is to take the id from match.params and then match it up with the page id passed down through props using javascript ‘find’.
This kind of works. I can console log the data for the individual page out from inside the ‘getPage’ method in the PageSingle component if I call it in the render method but the moment I try to access any individual values such as the id I get the old Cannot read property 'id' of undefined.
Probably not very clearly explained so please see code below:
PageList.js
import React from 'react';
import { Link } from 'react-router-dom';
const PageList = (props) => {
const pages = props.pages.map( (page) => {
return (
<div key={page.id}>
<Link to={`/pagelist/${page.id}`}>{page.title.rendered}</Link>
</div>
);
});
return <div className="page-list">{pages}</div>
};
export default PageList;
PageSingle.js
import React from 'react';
class PageSingle extends React.Component {
getPage = (props) => {
let thePage = props.pages.find(page => page.id === Number(props.match.params.pageId) );
**console.log(thePage); // 1. this works
console.log(thePage.id); // 2. this leads to error**
return thePage;
};
render() {
this.getPage(this.props);
return (
<h4>PageSingle</h4>
)
}
};
export default PageSingle;
JSON shown in console when it works – I’ve removed some so as not to take up too much space but you get the idea
{
content: {rendered: "Test Page 2 Text. Test Page 2 Text. Test Page 2 Text. Test Page 2 Text. Test Page 2 Text. ", protected: false}
date: "2019-09-30T13:38:47"
excerpt: {rendered: "Test Page 2 Text. Test Page 2 Text. Test Page 2 Text. Test Page 2 Text. Test Page 2 Text.", protected: false}
id: 14
link: "http://localhost/all_projects/wordpress/sites_main/my_projects/portfolio/wordpress/test-page-2/"
slug: "test-page-2"
status: "publish"
title: {rendered: "Test Page 2"}
type: "page"
__proto__: Object
}
The props are sent to page single using Browser Router. The routes themselves are defined in the App.js component and look like this. Not sure if this is relevant or not, probably not.:
Routes
<Route
path="/pagelist" exact
render={ (props) => <PageList {...props} pages={ this.state.pages } /> }
/>
<Route exact
path="/pagelist/:pageId"
render={(props) => <PageSingle {...props} pages={ this.state.pages } /> }
/>
Obviously, the end goal is to eventually display the relevant data via the render method but I actually need to access that data before I can do that.
It’s probably something really basic that I’m just not understanding.
Any pointers in the right direction would be much appreciated.
Thanks.
If you have the correct data in your console.log then I think this is because console.log executes after a small delay,
Try doing this and see if you get the property
setTimeout(function()
{
console.log(thePage.id)
}, 100);
usually keys are added after the console.log call
Hope it helps
Okay, for anyone interested, the answer lay in the fact that an array with an object inside of it was being returned in PageSingle.js.
The answer therefore lay in grabbin gthe correct page with an if statement and pushing the required values to an array and then accessing that with bracket notation:
let thisPage = [];
props.pages.map((page) => {
if (page.id === Number(props.match.params.pageId)) {
thisPage.push(page.id, page.title.rendered, page.content.rendered, page.featured_images);
}
return thisPage;
})
return (
<div>
<h4>{thisPage[1]}</h4>
<p>{thisPage[2]}</p>
</div>
)
Got to be a less convoluted way of doing this though so, any suggestions please let me know.
I want to create a list of component using strings.
Searching on Google/StackOverflow, this seems to be easy:
import Light from 'light.jsx';
[...]
getComponent()
{
let DynamicComponent = "Light";
return <DynamicComponent />;
}
Unfortunally, this approach doesn't work.
I get this error non console:
Warning: <Light /> is using uppercase HTML. Always use lowercase HTML
tags in React. Warning: The tag <Light> is unrecognized in this
browser. If you meant to render a React component, start its name with
an uppercase letter.
I've tried many combinations like:
return React.createElement(DynamicComponent, {}) };
return React.createElement("Light", {}) };
return <div> { React.createElement(DynamicComponent, {}) }</div>;
They all returns the same error.
Obviously if I use:
return <Light />
it works.
As you mentioned in the comment, you are putting all the import in a file like this:
import Light from './light.jsx';
import Fan from './fan.jsx';
export {
"Light": Light,
"Fan": Fan
}
And trying to use:
import * as Dynamic from 'allimport.js';
let DynamicComponent = "Dynamic.Light";
return <DynamicComponent />
Everything is proper, just remove the "" around "Dynamic.Light", it should be Dynamic.Light.
For more details check this answer: Dynamically rendering component from string: ReactJS
Sorry to bother you but I still get some errors:
(1) The import you wrote rise this error: "Unexpected token" at the first DoubleQuotes. All the export statement is red-underlined by IDE;
(2) I can't remove the doublequotes from Dynamic.Light because this assume I KNOW that a Light component exists.
But all this stuffs Im trying to make working is to prevent the developer to know them. I receive a list of what to render from DB managing this information in a loop. I need to be more flexible.
listOfComponentFromDB.map(name){
let DynamicComponent = "Dynamic."+name;
allRendered.push(<DynamicComponent />);
}
return allRendered;
With this approach to add a new component to the master render, it will be non necessary to modify the master render because you will have only to put the ne fan.jsx in the directory, add it to the import and INSERT the new row on the DB.