Sorry if there's a really simple solution, but building websites isn't my area of expertise.
I'm currently trying to create a Gatsby website where I have a Component nestled inside another Component but it shows a completely blank screen when I try to show the nestled Component. Following the answer from this question, I implemented a Layout Component that serves as a template for every site. In the future, I plan to tidy up the navigation bar and implement that into the Layout Component, but that's an issue for another time.
I'm currently trying to put in a Tile Component into my Layout that is also encapsulated inside my IndexPage, but my screen just shows nothing when I try to run it. I've tried to shorten the code so that it includes the minimum amount required.
I've taken a look at the Gatsby documentation and it appears that under the "Non-page components" section that I should use GraphQL, which I'm not sure how it works.
I suspect that the reason why it isn't working is that the Tile Component has to take in an imgLocation, altText, and caption properties, and somewhere along the way the code isn't working as intended.
Code:
index.js:
import * as React from "react"
import Layout from './Layout.js';
import Tile from './Tile.js';
// markup
const IndexPage = () => {
return (
<Layout pageTitle="Home">
<div id="main">
<div className="inner">
<h1>
<b>Portfolio</b>
</h1>
<p>
Here's all of the work that I've been commissioned to do over the past few years.
</p>
<h2>
<b>Christmas</b>
</h2>
<h3>
<b>Portrait</b>
</h3>
<section className="tiles">
<Tile imgLocation="imageFileLocationGoesHere" altText="descriptionOfImage" caption="Image Description" />
<Tile imgLocation="imageFileLocationGoesHere" altText="descriptionOfImage" caption="Image Description" />
</section>
<br />
<h3>
<b>Landscape</b>
</h3>
<section className="tiles">
<Tile imgLocation="imageFileLocationGoesHere" altText="descriptionOfImage" caption="Image Description" />
<Tile imgLocation="imageFileLocationGoesHere" altText="descriptionOfImage" caption="Image Description" />
</section>
</div>
</div>
{/* Footer */}
<footer id="footer">
{/* footer goes here */}
</footer>
</Layout>
)
}
export default IndexPage;
Tile.js (within the same folder as index.js):
import React from "react";
import '../css/main.css';
const Tile = (props) => {
const imgLocation = props.imgLocation;
const altText = props.altText;
const caption = props.caption;
return (
<article>
<span>
<img src={require({imgLocation}).default} alt={altText} onClick={() => {openModal(props)}} />
</span>
<br />
<p>{caption}</p>
</article>
);
}
export default Tile;
Layout.js (within the same folder as in index.js)
import * as React from 'react';
const Layout = ({pageTitle, children}) => {
return (
<main>
<title>{pageTitle}</title>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, user-scalable=no"
/>
{children}
</main>
)
}
export default Layout;
The problem you are facing here is that your Tile component is inside the /pages folder as you pointed here:
Tile.js (within the same folder as index.js):
So, Gatsby is trying to create a page based on the Tile component, hence, you are trying to render a page inside a page.
Move your component into another folder such as src/components/Tile and the issue should be gone.
Layout component also needs to be outside /pages folder.
Regarding the image, try to import it in the parent component and lift it to the child like:
import * as React from "react"
import Layout from './Layout.js';
import Tile from './Tile.js';
...
<Tile imgLocation={'./path/to/your/image.png'} />
And then:
<img src={imgLocation} alt={altText} onClick={() => {openModal(props)}} />
Or even drilling the image directly:
import Img from './path/to/your/image.png'
...
<Tile img={Img} />
Then:
const Tile = ({img:Img, altText, caption}) => {
return (
<article>
<span>
<Img />
</span>
<br />
<p>{caption}</p>
</article>
);
}
export default Tile;
Reassigning the img props as React component should also do the trick
Related
I am working on a React project.
I am facing this issue: I want the user to watch a video corresponding to a chest workout if he clicks on a video icon that is nested in a drawer of antd library component (this component also contains other information like the workout title...)
I want the user to be redirected to this page without the drawer being closed, (the drawer occupies 50% of the page's width, and the rest of the page is covered with a greyish bg color, but still visible), and then he can navigate again to the previous info if he clicks on a "back" btn.
The code of app.js
import { Route, Routes } from "react-router-dom";
// pages & components
import { ListOfExercises } from "./components/lists/ListOfExercises";
import Navbar from "./components/Navbar/Navbar";
import ChestWorkouts from "./pages/Chest";
import ChestVideoWorkouts from "./pages/ChestVideoWorkouts";
import Home from "./pages/Home";
function App() {
return (
<div className="App">
<Navbar />
<ListOfExercises></ListOfExercises>
<div className="pages">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/chest" element={<ChestWorkouts />} />
<Route path="/video-workout" element={<ChestVideoWorkouts />} />
</Routes>
</div>
</div>
);
}
export default App;
WorkoutInfosDrawer is a child of WorkoutDetails which is a child of WorkoutsSection which is a child of the ChestWorkouts page
and of WorkoutInfosDrawer.js:
import "./drawer_content_styles.scss";
import { WorkoutInfos } from "./WorkoutInfos";
export function WorkoutInfosDrawer({ workoutTitle, setsize }) {
function infos() {
let infos =
workoutTitle === "Barbell Flat Bench Press"
? {
description:
"The bench press is a classic exercise. Powerlifters do it to see who has the most pressing strength, gym rats use it to build up their pecs, and athletes utilize the bench for explosive pushing power. ",
benefits: {
b1: "This lift is a necessiry for powerlifters, since it’s one of the three lifts judged in a powerlifting meet.",
b2: "The bench press recruits muscles in the chest, triceps, and shoulders — so you’ll build a muscular torso",
b3: "Compared to other chest exercises, you can load the bench press up with a relatively heavy amount of weight.",
},
howToDo:
"Lay back down on a bench, arch your lower back slightly, and plant your feet on the floor. Pull your shoulder blades together to enhance stability and upper back strength. Grab the bar (varying grips) and squeeze the hand hard to flex the arm and grip muscles maximally. With the load unracked, think about pulling the barbell to the body to touch the sternum/base of the chest. Press the weight upwards, making sure to keep your back tight, and shoulder blades pulled together.",
}
: "";
return infos;
}
return (
<>
<WorkoutInfos
{...{
setsize,
workoutTitle,
}}
infos={infos()}
/>
</>
);
}
and of WorkoutInfos.js: , the Link tag is being used here :
import { Button } from "antd";
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import minus from "../../assets/img/minus.png";
import plus from "../../assets/img/plus-sign.svg";
import videoPlayer from "../../assets/img/video.svg";
import "./drawer_content_styles.scss";
export const WorkoutInfos = ({ workoutTitle, infos, setsize }) => {
return (
<div className="workout-infos" style={{ paddingBottom: paddingBottom }}>
<div className="workout-infos-left">
<div className="workout-infos-title">
<span>{workoutTitle}</span>
</div>
<div className="workout-infos-other-infos">
<div className="workout-infos-span1-wrapper">
<span>{infos?.description}</span>
</div>
<div className="workout-infos-span2-wrapper">
<span className="workout-infos-span1">
The workout's benefits :
</span>
<div className="workout-infos-span2-wrapper-div">
<span className="workout-infos-span2">{infos?.benefits?.b1}</span>
</div>
<div className="workout-infos-span2-wrapper-div">
<span className="workout-infos-span3">{infos?.benefits?.b2}</span>
</div>
{infos?.benefits?.b3 && (
<div className="workout-infos-span2-wrapper-div">
<span className="workout-infos-span4">
{infos?.benefits?.b3}
</span>
</div>
)}
</div>
<div className="workout-infos-howto-do">
<span className="workout-infos-howto-do-span1">How to do it :</span>
</div>
<div className="workout-infos-sign">
<div style={{ overflow: overflow, height: height }}>
<span className="workout-infos-sign-span">{infos?.howToDo}</span>
</div>
<Button className="workout-infos-sign-btn" onClick={handleBtnClick}>
{overflow === "hidden" ? (
<img src={plus} alt="" />
) : (
<img src={minus} alt="" />
)}
</Button>
</div>
</div>
</div>
<div className="workout-infos-right">
<Link to="/video-workout">
<Button className="workout-infos-sign-btn">
<img src={videoPlayer} alt="" />
</Button>
</Link>
</div>
</div>
);
};
Since the drawer component is nested deep inside <ChestWorkouts />, it's not going to render when you aren't rendering <ChestWorkouts /> anymore.
The key here is to structure your components such that the drawer component is not nested within any of the routes, so it doesn't disappear when its parent component does. Perhaps you could place the drawer component outside <Routes /> like you've done with <Navbar /> (which is the reason why Navbar doesn't disappear on route changes).
You can place the drawer at the root of your component tree and manage its state by passing it down other routed components or perhaps through redux.
So I'm trying to use the href at the bottom to link to Twitter? When putting an atag I get an error. is there another function I can use?
Ps. what I'm trying to do is on my home page have a picture that when the user clicks on it redirects them to Twitter.
I looked at other questions but it is not the same as mine. mine is trying to put a href inside a function.
Just added m carditem.JS components as well. Thank you !
import React from "react";
import "./Cards.css";
import CardItem from "./CardItem";
import { Link } from "react-router-dom";
function Cards() {
return (
<div className="cards">
<h1>Lost Fantom Saga Projects</h1>
<div className="cards__container">
<div className="cards__wrapper">
<ul className="cards__items">
<CardItem
src="images/img-9.jpg"
text="Lost Fantom Warrios"
label="Warriors"
path="/services"
/>
<CardItem
src="images/img-2.jpg"
text="Lost Fantom Disciples"
label="Disciples"
path="/services"
/>
</ul>
<ul className="cards__items">
<CardItem
src="images/img-3.jpg"
text="Fantom Degens"
label="Degens"
path="/services"
/>
<CardItem
src="images/img-4.jpg"
text="Coming Soon"
label="Coming Soon"
path="/products"
/>
<CardItem
src="images/img-4.jpg"
text="Coming Soon"
label="Coming Soon"
href="https://twitter.com/LostFantomSaga/"
target="_blank"
/>
</ul>
</div>
</div>
</div>
);
}
export default Cards;
import React from 'react';
import { Link } from 'react-router-dom';
function CardItem(props) {
return (
<>
<li className='cards__item'>
<Link className='cards__item__link' to={props.path}>
<figure className='cards__item__pic-wrap' data-category={props.label}>
<img
className='cards__item__img'
alt='Travel Image'
src={props.src}
/>
</figure>
<div className='cards__item__info'>
<h5 className='cards__item__text'>{props.text}</h5>
</div>
</Link>
</li>
</>
);
}
export default CardItem;
One simple approach that might suit your needs would be to use a <a> tag instead of the Link component.
Here's a quick and dirty CodeSandbox for how you could go about this, based on the code snippets you provided - https://codesandbox.io/s/lingering-sky-d4lz21?file=/src/CardItem.tsx. It demonstrates the ability to slightly alter the final render by using either props.path to use a Link component, or props.href to use a <a> tag (along with props.target for the target attribute).
Currently, I build a website in react.js and a problem came up. I think that when I click on a page that requires a script, the first time I enter the scripts does not work. but after when I refresh the page. suddenly the data appear. I think that my JavaScripts is no loading it, but if I refresh the page and it starts working
import React from 'react';
import "./Information.css";
function Information({imgStart,img, alt, name, age, gender,bio,qualification_acedemic,institution_acedemic,organisation,role,year,level,role_admin,level_admin,start_admin,end_admin
,area_expertise,book_pub,chp_book_pub,title_Areas,role_Areas,title_consult,role_consult,organisation_consult,fromTo_consult
,award,institution_award,year_award,activity_contribute,fromTo_contribute,role_contribute,name_degree,name_candidates,title_thesis,academic_level,academic_teach,course_teach,hourContact_teach,number_student_teach}) {
return (
<>
<div className="container_details">
<div className="row_details"
style={{display: "flex", flexDirection: imgStart === 'start' ? "row-reverse" : "row" }}>
<div className="col-personal-logo">
<img src={img} alt={alt} className="personal-image"/>
<h2>{name}</h2>
<p>Age:{age}</p>
<p>Gender:{gender}</p>
<p></p>
</div>
<div className="col-personal">
<button class="accordion">Biography</button>
<div class="panel">
<p>{bio}</p>
</div>
<button class="accordion">Academic Qualification</button>
<div class="panel">
<p>Qualification: {qualification_acedemic}</p>
<p>Institution: {institution_acedemic}</p>
</div>
<button class="accordion">Professional</button>
<div class="panel">
<p>Organisation: {organisation}</p>
<p>Role: {role}</p>
<p>Year: {year}</p>
<p>Level: {level}</p>
</div>
</div>
</div>
</div>
</>
)
}
export default Information
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.0/css/all.css"
integrity="sha384-OLYO0LymqQ+uHXELyx93kblK5YIS3B2ZfLGBmsJaUyor7CpMTBsahDHByqSuWW+q" crossorigin="anonymous">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>UOW Portal</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
<script>
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
/* Toggle between adding and removing the "active" class,
to highlight the button that controls the panel */
this.classList.toggle("active");
/* Toggle between hiding and showing the active panel */
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
</script>
</html>
app.js
import React from 'react';
import "./App.css"
import Navbar from './components/Navbar';
import { Switch, Route} from 'react-router';
import { BrowserRouter } from 'react-router-dom'
import Home from './components/pages/HomePage/Home'
import Footer from './components/pages/Footer/Footer';
import Service from './components/Service';
import Info from './components/pages/Info/Info';
import infoMs from './components/pages/Info/infoMs';
function App(){
return(
<BrowserRouter>
<Navbar />
<Switch>
<Route path='/' exact component={Home}/>
<Route path='/service' exact component={Service}/>
<Route path='/phua' component={Info}/>
<Route path='/foong' component={infoMs}/>
</Switch>
<Footer />
</BrowserRouter>
);
}
export default App;
I don't think that's the way React meant to works!
REASON
React uses what known as Client-Side Rendering, so things like getting an element using getElementById or getElementByClassName shouldn't work. Because, (CMIIW) the rendering of the elements is not finished yet when your getElementById scripts already running, so that it cannot find the elements.
SOLUTION
However, if you want to make your view respond to click event, you can put your function on the component. Meaning, instead creating an event listener using addEventListener, you should do:
<button class="accordion" onClick={/*YOUR CLICK LISTENER HERE*/}>Biography</button>
not only that, you should create a state of open/close by using a React State (either hooks or component based state). And your click handler should toggle the state true or false.
However, as words are hard to digest 🥴, let me show a code example 😄.
Create a new component Accordion, like this:
function Accordion({ children, title }) {
const [show, setShow] = useState(false)
const toggle = () => setShow(state => !state)
return (
<div>
<button class="accordion" onClick={toggle}>{title}</button>
{show &&
<div class="panel">
{children}
</div>
}
</div>
)
}
Then use it like this:
function Information(....) {
......
<Accordion>
<div>
<p>Qualification: {qualification_acedemic}</p>
<p>Institution: {institution_acedemic}</p>
</div>
</Accordion>
......
}
This Accordion component should have the ability to open and close independently. If you want to make it dependent of the other, you can implement more advanced state or use a third party component, maybe this component.
CONCLUSION
I think you should use the React way of making your UI responsive and not trying the vanilla way which actually are like fighting with React.
I have been trying to use material-ui and iterate over it inside an array ( for creating ratings for some items like in e-commerce sites). The code isn't working. On my localhost server, it's not showing any stars at all. Before I made it dynamic, it was working all fine, then I added props to my functional component as per to make it dynamic. Everything else is working just fine except that it's not accepting my matrial-ui icon inside the array for me to iterate over. Moreover, the import statement says "it's value is never read although it's imported"
My code: Product.js:
import React from "react";
import "./Product.css";
import StarRateIcon from "#material-ui/icons/StarRate";
function Product({ id, title, image, price, rating }) {
return (
<div className="product">
<div className="product_info">
<p>{title}</p>
<p className="product_price">
<small>$</small>
<strong>{price}</strong>
</p>
<div className="product_rating">
{Array(rating)
.fill()
.map((_, i) => (
<p StarRateIcon className="star" />
))}
</div>
</div>
<img src={image} alt="" />
<button>Add to Basket</button>
</div>
);
}
export default Product;
My home.js file :
import React from "react";
import "./Home.css";
import Product from "./Product";
function Home() {
return (
<div classname="home">
<div className="home_container">
<img
className="home_image"
src="https://m.media-amazon.com/images/G/01/digital/video/sonata/US3P_JOKER_IMAGE_ID/be07783e-2738-4aaf-b90c-d0ec474d15ae._UR3000,600_SX1500_FMwebp_.jpg"
/>
<div className="home_row">
<Product
id="890778"
title="Description"
price={99.99}
image="https://m.media-amazon.com/images/I/71BGLa7IFtL._AC_UY218_.jpg"
rating={5}
/>
<Product />
</div>
</div>
</div>
);
}
export default Home;
Help Somebody! I can use emoji snippets but I really want this to work. I have imported StarRateIcon and used it. It isn't working.
Looks like you accidentally put a 'p' in front of your icon component name. You have <p StarRateIcon className="star" /> when it should be <StarRateIcon className="star" />
You're rendering a p tag with no content with an invalid attribute, StarRateIcon. It's the reason you're not seeing anything rendered. If you inspect the HTML, you'll most likely see the p tags. You may also see errors in the console about invalid attributes. Your code should look something like this:
Array(rating).fill().map(() => <StarRateIcon className="star" />)
I'm working with Nextjs and Reactjs. I have set the Layout.js file for my application UI.
I wonder why my console returns me:
Invariant Violation: React.Children.only expected to receive a single
React element child.
Here's my layout.js :
export default ({ children, title = 'This is the default title' }) => (
<div>
<Head>
<title>{ title }</title>
<meta charSet='utf-8' />
<meta name='viewport' content='initial-scale=1.0, width=device-width' />
</Head>
<div className={style.layout}>
<div>
<div className={style.header}>
<div className= {style.headbar}>
<div className={style.headerLeft}>
<Logo className={style.logo}/>
</div>
<div className={style.headerRight}>
<MenuContainer className={style.menu}/>
</div>
</div>
<div className={style.chatbox}>
<ChatContainer/>
</div>
</div>
{ children }
<div className={style.footer}>
<Link to="/quote" className={style.quote}>
Click here
</Link>
<SocialMedia/>
<Subscription/>
</div>
</div>
</div>
</div>
)
My wrappedComponent.js:
const Index = () => (
<Provider store={store}>
<Layout>
<Home/>
</Layout>
</Provider>
)
I can't figure out what is wrong, it seems to me everything is great, if someone have any hint, would be great.
Thanks.
The problem was that my data structure corresponded to an another framework. So there was some tiny details that make NextJS crush - like "props" calls inside my React Links, this kind of stuff-. So if someone have the same problem, double check you framework data structure's configuration