React Redux Image Wont load - javascript

So this could honestly be as simple as just over looking it and staring for so long and being new to react but on my section component I'm loading in my backgroundImg prop wont load the image and I cant figure it out. My pictures are in the public folder and my code is in the src components folder
Also, I can get images to load in the file just not when I'm calling them through prop
Home.js This is where I am calling my component and trying to load the file in through the prop type
import React from 'react'
import styled from 'styled-components'
import Section from './Section'
function Home() {
return (
<Container>
<Section
title="Model S"
description="Order Online for Touchless Delivery"
backgroundImg='/public/pictures/model-s.jpg'
leftBtnText="Custom Order"
rightBtnText="Existing Inventory"
/>
<Section
title="Model E"
description="Order Online for Touchless Delivery"
backgroundImg=".\Pictures\model-e.jpg"
leftBtnText="Custom Order"
rightBtnText="Existing Inventory"
/>
<Section />
<Section />
</Container>
)
}
export default Home
//Home and styled help you stlye the component without using css
const Container = styled.div`
height: 100vh;
`
Section.js The component for the Screen
import React from 'react'
import styled from 'styled-components'
//props are just parameters you can set when calling the component
function Section(props) {
return (
<Wrap bgImg={props.backgroundImg}>
<ItemText>
<h1>{props.title}</h1>
<p>{props.description}</p>
</ItemText>
<Buttons>
<ButtonGroup>
<LeftButton>
{props.leftBtnText}
</LeftButton>
<RightButton>
{props.rightBtnText}
</RightButton>
</ButtonGroup>
<DownArrow src='/Pictures/down-arrow.svg' />
</Buttons>
</Wrap>
)
}
export default Section
const Wrap = styled.div`
width: 100vw;
height: 100vh;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
`
const ItemText = styled.div`
padding-top: 15vh;
text-align: center;
`
const ButtonGroup = styled.div`
display: flex;
margin-bottom: 30px;
#media (max-width: 786px){
flex-direction: column;
}
`
const LeftButton = styled.div`
background-color: rgba(23, 26, 32, 0.8);
height: 40px;
width: 256px;
color: white;
display: flex;
justify-content: center;
align-items: center;
border-radius: 100px;
opacity: 0.85;
text-transform: uppercase;
font-size: 12px;
cursor: pointer;
margin: 8px;
`
const RightButton = styled(LeftButton)`
background: white;
opacity: 0.65;
color: black;
`
const DownArrow = styled.img`
margin-top: 20px;
height: 40px;
overflow-x: hidden;
animation: animateDown infinite 1.5s;
`
const Buttons = styled.div`
`
Thanks for the help.

I haven't tested this, but it looks like you didn't use the Wrap bgImg prop in the styled component. There is background-size, background-position, background-repeat, but not background-image using the prop.
Example:
background-image: ${props => props.bgImg || ''};
https://styled-components.com/docs/basics#passed-props

Related

Get ID of fully visible component

I tried to make code showing the number of component which is currently fully visible.
I used Intersection Observer API and to make it, used callback entry.intersectionRatio === 1.0.
I want to remark currently fully visible component at state currentView but it doesn't show anything.
I think currentView is not changed, althought I use useEffect
May I know which part is wrong and how to fix it??
code :
import styled from "styled-components";
import { useState, useEffect } from "react";
export default function App() {
const [currentView, setCurrentView] = useState();
useEffect(() => {
const components = document.querySelectorAll(".comp");
const componentObserver = new IntersectionObserver(function (
entries,
observer
) {
entries.forEach(function (entry) {
if (entry.isIntersecting && entry.intersectionRatio === 1.0) {
setCurrentView(entry.target.id);
}
});
});
components.forEach((comp) => {
componentObserver.observe(comp);
});
}, [currentView, setCurrentView]);
return (
<Wrap>
<div className="fixed">currentcomponent : {currentView}</div>
<div id="part-1" className="compo1 comp">
components 1
</div>
<div id="part-2" className="compo2 comp">
components 2
</div>
<div id="part-3" className="compo3 comp">
components 3
</div>
</Wrap>
);
}
const Wrap = styled.div`
border: 3px solid black;
width: 100vw;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
.fixed {
position: sticky;
top: 0;
}
.compo1 {
border: 3px solid red;
display: flex;
justify-content: center;
align-items: center;
width: 90vw;
height: 90vh;
}
.compo2 {
border: 3px solid blue;
display: flex;
justify-content: center;
align-items: center;
width: 90vw;
height: 90vh;
}
.compo3 {
border: 3px solid green;
display: flex;
justify-content: center;
align-items: center;
width: 90vw;
height: 90vh;
}
`;
CodeSandBox :
CodeSandBox

Looking to place text over image in React

I have a Splideslide element in react and am looking to move the description text over the image for each element. Currently the code I have is:
import {useEffect, useState} from "react";
import styled from "styled-components";
import {Splide, SplideSlide} from "#splidejs/react-splide";
import "#splidejs/splide/dist/css/splide.min.css";
function Popular() {
const [popular, setPopular] = useState([]);
useEffect(() => {
getPopular();
}, []);
const getPopular = async() => {
const api = await fetch(`https://api.spoonacular.com/recipes/random?apiKey=${process.env.REACT_APP_API_KEY}&number=9`);
const data = await api.json();
console.log(data);
setPopular(data.recipes)
console.log(data.recipes)
}
return (
<div>
<Wrapper>
<h3>Popular Picks</h3>
<Splide options = {{
perPage:4,
arrows: false,
pagination: false,
drag: 'free',
gap: "4rem",
}}>
{popular.map((recipe) =>{
return (
<SplideSlide>
<Card>
<Gradient/>
<p>{recipe.title}</p>
<img src={recipe.image} alt={recipe.title}/>
</Card>
</SplideSlide>
);
})}
</Splide>
</Wrapper>
</div>
)
}
const Wrapper = styled.div`
margin: 4rem 0rem;
postion: absolute;
`;
const Card = styled.div`
min-height: 25rem;
overflow: hidden;
postion: relative;
img {
border-radius: 2rem;
postion: absolute;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
p {
position: absolute;
z-index: 10;
left: 50%;
bottom: 0%;
transform: translate(-50%, 0%);
color: black;
width: 100%;
text-align: center;
font-weight: 600;
font-size: 1rem;
height: 40%;
display: flex;
justify-content: center;
align-items: center;
}
`;
const Gradient = styled.div`
z-index: 3
postion: absolute;
width: 100%;
height: 100%;
background: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0.5))
`;
export default Popular
Theoretically I believe this should be able to move the text on the image but for some reason it is not working as intended. The full project can be seen in the repository here: REPO. Feel free to comment for further information or any clarifications.
Maybe because of your multiple
postion: absolute;
instead of
position: absolute;
;)

How to change content/components within a js react page?

To clarify I'm working a react page that would show the user one piece of content that will be displayed on the page. When the user clicks on a link to said piece of content that they would like to see on the page.
The structure of the page goes like this. There will be a navbar that is specific to the page. The navbar has links to the components/content I'm also using styled components for this project the navbar looks like this
The servantclassnavbar file.
import react from 'react'
import styled from 'styled-components'
import { Link } from 'react-router-dom'
//useable react icon
import {FaCaretDown} from 'react-icons/fa'
const Navbarcontainer = styled.ul`
background: #D3D3D3;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
display: flex;
justify-content: center;
`
const Dropdownbtn = styled.div`
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
cursor: pointer;
&:hover{
color: cyan;
background: grey;
transition: ease-in-out 0.5s;
}
`
const Dropdowncontent = styled.div`
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
`
const Dropdownli = styled.li`
display: inline-block;
&:hover {
color: cyan;
background: grey;
transition: ease-in-out 0.4s;
}
&:hover ${Dropdowncontent} {
display: block;
}
`
const Dropdownnavlinks = styled(Link)`
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
&:hover {
color: cyan;
background-color: grey;
transition: ease-in-out 0.4s;
}
`
function Servantclassesnavbar(){
return(
<>
<Navbarcontainer>
<Dropdownli>
<Dropdownbtn>
Knight Classes<FaCaretDown />
</Dropdownbtn>
<Dropdowncontent>
<Dropdownnavlinks to="/saberclass">Saber</Dropdownnavlinks>
<Dropdownnavlinks to="/archerclass">Archer</Dropdownnavlinks>
<Dropdownnavlinks to="/lancerclass">Lancer</Dropdownnavlinks>
</Dropdowncontent>
</Dropdownli>
</Navbarcontainer>
</>
)
}
export default Servantclassesnavbar;
Here is a the page that I want to have it act as a home page for the all the other components to display their content in. You can ignore the 'Navbar' and 'sidebar' they are just navigations to other pages for this site.
import React,{useState} from "react";
import Navbar from "../componets/navbar";
import Sidebar from "../componets/sideBar";
import styled from "styled-components";
import Servantclassesnavbar from "../servantclassescomponets/servantclassesnavbar";
import Introduction from "../servantclassescomponets/Introduction"
import Saberclass from '../servantclassescomponets/Saberclass'
import Lancerclass from '../servantclassescomponets/Lancerclass'
import Archerclass from "../servantclassescomponets/Archerclass"
import {BrowserRouter as Router, Switch, Route} from "react-router-dom";
const Displayedserventclasscontainer = styled.div`
border: 1px solid black;
margin: auto;
width: 95vw;
height: 280vw;
background: rgb(130,141,162);
background: linear-gradient(274deg, rgba(130,141,162,0.938813025210084) 0%, rgba(66,116,150,0.6306897759103641) 50%, rgba(132,152,187,1) 100%);
#media screen and (max-width: 1024px){
min-height: 100vh;
}
#media screen and (max-width: 768px){
min-height: 230vh;
}
#media screen and (max-width: 540px){
min-height: 320vh;
}
#media screen and (max-width: 414px){
min-height: 350vh;
}
#media screen and (max-width: 375px){
min-height: 415vh;
}
#media screen and (max-width: 360px){
min-height: 450vh;
}
#media screen and (max-width: 320px){
min-height: 530vh;
}
`;
function Servantclasses (){
const [isOpen, SetIsOpen] = useState(false);
function toggle (){
SetIsOpen(!isOpen)
}
return(
<>
<Navbar toggle={toggle}/>
<Sidebar isOpen={isOpen} toggle={toggle}/>
<Servantclassesnavbar />
<Displayedserventclasscontainer>
<Router>
<Switch>
<Route path="/" component={Introduction} />
<Route path="/saberclass" component={Saberclass} />
<Route path="/lancerclass" component={Lancerclass} />
<Route path="/archerclass" component={Archerclass} />
</Switch>
</Router>
</Displayedserventclasscontainer>
</>
)
}
export default Servantclasses;
Last here is an example of the component/content I'm trying to display on the page.
import react from 'react'
import styled from 'styled-components'
import sabercard from '../assets/sabercard.png'
const Maincontainer = styled.div`
margin: auto;
width: 75vw;
height: 275vw;
text-align: center;
`
const Classnameheader = styled.h1`
margin-bottom: 2%;
font-size: 2.5rem;
border-bottom: 3px solid black;
`
const Classcardimg = styled.div`
display: flex;
justify-content: center;
border-bottom: 3px solid black;
> img {
width: 15vw;
height: 30vw;
}
`
const Loreheadercontainer = styled.h2`
font-size: 2rem;
border-bottom: 3px solid black;
`
const Classlorecontainer = styled.div`
font-size: larger;
`
<Maincontainer>
<Classnameheader>Saber</Classnameheader>
<Classcardimg><img src={sabercard} alt="The Servant class card image" /></Classcardimg>
<Loreheadercontainer>Saber Lore</Loreheadercontainer>
<Classlorecontainer>Servants that are placed in this class are legendary figures who took up the sword in their life.
some are known for choosing to master their swordsmanship. others only used it briefly, but they are a Saber all the same.</Classlorecontainer>
At first I tried using react-router as you can see in the page file that houses all the content, and that's when I realize that react-router changes the whole page leaving a blank page. How would I make it so when I click on one the links the content with in the page's 'Displayedserventclasscontainer' will display just the content the user wants to see within that page?
Since the Servantclassesnavbar uses the Link component, it should be inside of the Router component as follow:
return(
<Router>
<Navbar toggle={toggle}/>
<Sidebar isOpen={isOpen} toggle={toggle}/>
<Servantclassesnavbar />
<Displayedserventclasscontainer>
<Switch>
<Route path="/" component={Introduction} />
<Route path="/saberclass" component={Saberclass} />
<Route path="/lancerclass" component={Lancerclass} />
<Route path="/archerclass" component={Archerclass} />
</Switch>
</Displayedserventclasscontainer>
</Router>
)
And any component used outside of the Switch will be displayed on all pages, which I think is what you are trying to achieve.

React styled-component don't pass props

What I did:
I'm passing some props to functional component Stat.jsx.
What I expected:
I need to pass some background gradient color codes as a string type prop to the Stat.jsx component to make custom color elements.
What happened:
Props aren't passing to the Stat.jsx, also props object is empty.
Stat.jsx
import React from 'react';
import styled from 'styled-components';
const Stat = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding: 0 2.5em;
width: auto;
height: 2.5em;
border-radius: 0.5em;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.2);
background: linear-gradient(160deg, ${(props) => console.log(props) });
font-size: 1.8em;
font-family: Rubik-Medium;
color: #fff;
`;
// console.log(props) is returning object: { children: "1000", theme: {} }
export default ({ value }) => <Stat>{value}</Stat>;
Stats.jsx
import React from 'react';
import Stat from './Stat';
import styled from 'styled-components';
const Stats = styled.div`
display: flex;
`;
export default () => (
<div>
<Stats>
<Stat value="1000" background="#F4D03F, #16A085" />
</Stats>
</div>
);
Quick Fix
Because you don't pass the background prop to the actual Stat component:
export default (props) => <Stat {...props}>{props.value}</Stat>;
Explanation
A better way to illustrate the issue is by renaming your components:
import React from 'react';
import styled from 'styled-components';
const StyledStat = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding: 0 2.5em;
width: auto;
height: 2.5em;
border-radius: 0.5em;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.2);
background: linear-gradient(160deg, ${(props) => console.log(props) });
font-size: 1.8em;
font-family: Rubik-Medium;
color: #fff;
`;
export default function Stat(props){
const { value } = props;
return (
<StyledStat {...props}>
{value}
</StyledStat>;
};
Styled components props comes from the ThemeProvider usually, this is why you see a theme props while console.logging inside your styled.div
Usually in App.js you have something like that:
// src/App.jsx
import React from 'react'
import { ThemeProvider } from 'styled-components';
const theme: {
colors: {
primary: blue,
}
}
const App = () => (
<ThemeProvider theme={theme}>
<Stat />
</ThemeProvider>
)
export default App;
you can access these attributes with
${(props) => props.theme.colors.primary }
because styled-components provides its theme props to every StyledComponents (there is a Context Provider/consumer thing behind)
import React from 'react';
import styled from 'styled-components';
const Stat = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding: 0 2.5em;
width: auto;
height: 2.5em;
border-radius: 0.5em;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.2);
background: linear-gradient(160deg, ${(props) => props.theme.colors.primary} });
font-size: 1.8em;
font-family: Rubik-Medium;
color: #fff;
`;

Styled components cause react-dom.production.min.js:4482 Error: Minified React error #31;

Styled components cause build crash
Guys, I have a problem with styled components ;/.
I'm using create-react-app and everything works fine until I "npm run build" and deploy the app on my FTP.
I keep getting this weird error and have not found any solution online. My code is attached below. Should be plain and simple.
Any ideas?
import styled from 'styled-components';
import countriesJSON from './countries.json';
const Container = styled.div`
max-width: 1200px;
margin: 0 auto;
`;
const Wrapper = styled.div`
display: flex;
flex-direction: column;
height: 100vh;
justify-content: center;
align-items: center;
`;
const Button = styled.button`
background: whitesmoke;
border-radius: 3px;
height: 5vh;
width: 20vw;
border: 2px solid orange;
color: 'slategrey';
margin: 0 1em;
padding: 0.25em 1em;
&:hover {
background: whitesmoke;
transform: scale(1.2);
`;
const Text = styled.h1`
font-size: calc(2vw + 10px);
font-weight: bold;
text-align: center;
color: whitesmoke;
`;
const Paragraph = styled.p`
color: whitesmoke;
font-size: calc(1vw + 10px);
`;
const CountryWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: center;
#media (min-width: 600px) {
flex-direction: row;
}
`;
const CountryDetailsWrapper = styled.div`
margin: 10px;
text-align: center;
`;
const CountryImgWrapper = styled.div`
img {
height: 40vh;
margin: 0 auto;
width: 90vw;
padding: 10px;
}
#media (min-width: 596px) {
img {
width: 30vw;
height: 30vh;
}
}
`;
class Homepage extends Component {
constructor(props) {
super(props);
this.state = {
randomCountry: '',
isCountryWrapperVisible: false,
countryFlag: '',
countryRegion: '',
countryCurrency: '',
countryCapital: '',
countryPopulation: '',
countryTimezone: ''
}};
generateRandomCity = () => {
let num = Math.floor(Math.random() * countriesJSON.length);
this.setState({
randomCountry: countriesJSON[num].name
});
};
componentDidUpdate() {
this.fetchCountryInfo();
}
fetchCountryInfo = () => {
fetch(`https://restcountries.eu/rest/v2/name/${this.state.randomCountry}`)
.then(res => res.json())
.then(response =>
this.setState({
countryFlag: response[0].flag,
countryCapital: response[0].capital,
countryRegion: response[0].region,
countryCurrency: response[0].currency,
countryPopulation: response[0].population,
isCountryWrapperVisible: true
})
);
};
render() {
return (
<Container>
<Wrapper>
<Text> Test Your Knowledge of Flags </Text>
<Button onClick={this.generateRandomCity}> HIT ME! </Button>
{this.state.isCountryWrapperVisible && (
<CountryWrapper>
<CountryImgWrapper>
<img src={this.state.countryFlag} alt='flag' className='img-fluid'/>
</CountryImgWrapper>
<CountryDetailsWrapper>
<Paragraph> Name: {this.state.randomCountry} </Paragraph>
<Paragraph> Capital: {this.state.countryCapital} </Paragraph>
<Paragraph> Region: {this.state.countryRegion} </Paragraph>
<Paragraph> Population: {this.state.countryPopulation} </Paragraph>
</CountryDetailsWrapper>
</CountryWrapper>
) }
</Wrapper>
</Container>
)
}
}
export default Homepage;```
It turns out the problem lied in global-style object within parent component I had to recode.

Categories