Background image only shows up after reloading the page - reactjs

I'm trying to import an image as I usually do on React and using that value as a background image for a styled component, the first page that renders seems to use the background fine, but then when navigating the application with Links from react-router it doesn't seem to load the background for any of the components inside the router. I have to reload each component to see the actual background.
import React from "react";
import MiningBackground from "assets/backgrounds/miningBackground.jpg";
import styled from "#emotion/styled";
const MiningPage = () => {
return <BackgroundContainer key="mining-background"></BackgroundContainer>;
};
const BackgroundContainer = styled.div`
background-image: url(${MiningBackground});
background-repeat: no-repeat;
background-size: cover;
opacity: 0.3;
min-height: 100vh;
min-width: 100vw;
background-color: "#0A2836";
color: "#0A2836";
`;
export default MiningPage;
After further checking, it looks like the router is not returning the components at all, I'll attach the router and the navigation.
The Drawer:
import {
faHome,
faGem,
faCoins,
faSpaceShuttle,
} from "#fortawesome/free-solid-svg-icons";
import { Divider, Drawer, List, Toolbar, Typography } from "#material-ui/core";
import React from "react";
import AMenuItem from "components/atoms/AMenuItem";
import styled from "#emotion/styled";
import MadeByCommunityBlack from "assets/MadeByTheCommunity_Black.png";
const SideMenu: React.FC = () => {
return (
<StyledDrawer variant="permanent" open>
<div>
<Toolbar />
<StyledList>
<AMenuItem link="/" icon={faHome} text="Home" />
<AMenuItem link="/mining" icon={faGem} text="Mining" />
<AMenuItem link="/trading" icon={faCoins} text="Trading" />
<AMenuItem link="/fleet" icon={faSpaceShuttle} text="Fleet" />
<Divider />
</StyledList>
</div>
<TradeMarkContainer>
<StyledImage
src={MadeByCommunityBlack}
alt="Made by the star citizen community official logo"
/>
<Typography variant="caption">
Star Citizen®, Roberts Space Industries® and Cloud Imperium ® are
registered trademarks of Cloud Imperium Rights LLC.
</Typography>
</TradeMarkContainer>
</StyledDrawer>
);
};
const StyledDrawer = styled(Drawer)`
.MuiDrawer-paper {
z-index: 980;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
padding: 0px 10px 10px 10px;
width: 190px;
}
`;
const TradeMarkContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
`;
const StyledList = styled(List)`
background-color: "#0A2836";
`;
const StyledImage = styled.img`
width: 150px;
`;
export default SideMenu;
The Router:
import FleetPage from "components/pages/FleetPage";
import MiningPage from "components/pages/MiningPage";
import TradingPage from "components/pages/TradingPage";
import React from "react";
import { Route, Router, Switch } from "react-router-dom";
import HomePage from "../components/pages/HomePage";
import { createBrowserHistory } from "history";
import SideMenu from "components/organisms/SideMenu";
import TopBar from "components/organisms/TopBar";
const Routes = () => {
const history = createBrowserHistory();
return (
<Router history={history}>
<TopBar />
<SideMenu />
<Switch>
<Route path="/fleet" component={FleetPage} />
<Route path="/trading" component={TradingPage} />
<Route path="/mining" component={MiningPage} />
<Route path="/" component={HomePage} />
</Switch>
</Router>
);
};
export default Routes;

The issue was I was importing Router and not BrowserRouter from react-router-dom. Changing that and removing the history prop did the trick.

Related

Component content not imported when importing styled components

I am building a site using React and have decided to use Styled Components. I have a component that is styled with Styled Components and is receiving a prop from my homepage where I am using an instance of this component. I have the styling being pulled into the homepage, but it is not pulling in the content of the component. When if I just pull in the whole component it pulls in the content fine, but it doesn't allow me to pass the prop, but if I import the component styling it doesn't pull in the content of the component, but the prop passes properly. So I need some help with how to pull in the content and styling and get the prop to pass.
I am pretty new to Gatsby and Styled Components so thanks for any help.
My Component Code
import React from 'react'
import styled from "styled-components"
import { useStaticQuery, graphql } from 'gatsby'
export const WhyChooseSection = styled.section`
border-bottom: 1px solid var(--charcoal);
`
export const WhyChooseH2 = styled.h2`
display: ${(props) => props.displayH2};
text-align: center;
`
export const WhyChooseContent = styled.div`
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
width: 100%;
max-width: 1160px;
margin: 0 auto;
padding-top: 40px;
padding-bottom: 40px;
column-gap: 100px;
row-gap: 30px;
#media(min-width: 992px) {
justify-content: space-between;
column-gap: 0;
}
.why-icon {
width: 180px;
height: 145px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20px;
p {
margin-bottom: 0;
font-size: 19px;
font-weight: var(--font-bold);
}
}
`
export function WhyChooseIcons() {
const data = useStaticQuery(graphql`
{
whyChooseIcons: allWp {
nodes {
acfOptionsOfficeSettings {
whyChooseInteriorDetails {
whyChooseIcons {
whyChooseIconGraphic {
altText
id
sourceUrl
}
whyChooseIconTitle
}
}
}
}
}
}
`)
return (
<>
{data.whyChooseIcons.nodes.map((node, index) => (
<WhyChooseSection key={index}>
<WhyChooseH2>Why Choose Interior Details?</WhyChooseH2>
<WhyChooseContent>
{node.acfOptionsOfficeSettings.whyChooseInteriorDetails.whyChooseIcons && node.acfOptionsOfficeSettings.whyChooseInteriorDetails.whyChooseIcons.map((item) => (
<div className='why-icon' key={item.whyChooseIconGraphic.id}>
<img src={item.whyChooseIconGraphic.sourceUrl} alt={item.whyChooseIconGraphic.altText} />
<p>{item.whyChooseIconTitle}</p>
</div>
))}
</WhyChooseContent>
</WhyChooseSection>
))}
</>
)
}
export default WhyChooseIcons
My Homepage Code
import * as React from "react"
// import styled from "styled-components"
import { graphql } from 'gatsby'
import Seo from "../components/seo"
import Hero from '../components/heroComponent'
import { WhyChooseSection } from '../components/whyChooseIcons'
import { WhyChooseH2 } from '../components/whyChooseIcons'
import { WhyChooseContent } from '../components/whyChooseIcons'
import HomeProducts from '../components/homeProducts'
import HomeTestimonials from '../components/testimonials'
import HomeNewHomes from '../components/homeNewHomes'
import HomeFamilyTreatment from '../components/homeFamilyTreatment'
import HomeSolutions from '../components/homeSolutions'
import HomeMotorization from '../components/motorizationComps'
import HomeBrands from '../components/homeBrands'
import CTAOne from '../components/ctaOne'
const IndexPage = (hero) => {
const heroData = hero.data.homeHero
return (
<>
{heroData.edges.map(({ node }, index) => (
<Hero key={index} heroTitle={node.template.homePage.heroH1} heroSubTitle={node.template.homePage.heroParagraph} heroBg={node.template.homePage.heroBackground.gatsbyImage} heroBtnOneText={node.template.homePage.heroButton1Text} heroBtnOneURL={node.template.homePage.heroButton1Url} heroBtnTwoText={node.template.homePage.heroButton2Text} heroBtnTwoURL={node.template.homePage.heroButton2Url} />
))}
<WhyChooseSection>
<WhyChooseH2 displayH2="none"></WhyChooseH2>
<WhyChooseContent></WhyChooseContent>
</WhyChooseSection>
<HomeProducts />
<HomeTestimonials />
<HomeNewHomes />
<HomeFamilyTreatment />
<HomeSolutions />
<HomeMotorization />
<HomeBrands />
<CTAOne />
</>
)
}
export default IndexPage
export const Head = () => <Seo title="Home" />
export const HeroContent = graphql`
{
homeHero: allWpPage(filter: {template: {templateName: {eq: "Home Template"}}}) {
edges {
node {
template {
... on WpHomeTemplate {
homePage {
heroH1
heroParagraph
heroButton1Text
heroButton1Url
heroButton2Text
heroButton2Url
heroBackground {
gatsbyImage(placeholder: BLURRED, width: 1920)
altText
}
}
}
}
}
}
}
}
`
Since you only want to pass a prop into your <WhyChooseIcons> component and that the component itself renders its own content, there is no need to provide any children node to it in the consuming parent.
Simply update your <WhyChooseIcons> component to accept a prop that it will pass to its inner child. Let's name it displayH2 and we can simply pass it into the <WhyChooseH2> component by doing this: <WhyChooseH2 displayH2={displayH2}>. So your component definition now looks like this:
export function WhyChooseIcons({ displayH2 }) {
// Rest of the component logic here
return (
<>
{data.whyChooseIcons.nodes.map((node, index) => (
<WhyChooseSection key={index}>
<WhyChooseH2 displayH2={displayH2}>Why Choose Interior Details?</WhyChooseH2>
{/* Other content here */}
</WhyChooseSection>
))}
</>
)l
};
Then in the file where you consume this component, it is just a matter of passing "none" to the prop:
<WhyChooseSection displayH2="none">
HOWEVER this feel like a XY problem to me, because all you want is to control the conditional rendering of this component. What you can do is to create a prop on your component that determines whether <WhyChosseH2> should be rendered or not.
export const WhyChooseH2 = styled.h2`
text-align: center;
`
export function WhyChooseIcons({ shouldHideH2 }) {
return (
<>
{data.whyChooseIcons.nodes.map((node, index) => (
<WhyChooseSection key={index}>
{!shouldHideH2 && <WhyChooseH2>Why Choose Interior Details?</WhyChooseH2>}
{/* Other content here */}
</WhyChooseSection>
))}
</>
)
}
Then you can just control H2 rendering with a true/false boolean:
{/* To show it, just don't set the prop */}
<WhyChooseIcons />
{/* To hide it, both ways are valid */}
<WhyChooseIcons shouldHideH2 />
<WhyChooseIcons shouldHideH2={true} />

Can't style #mui Avatar icon with styled-components

I'm playing around with styled-components and having troubles working with material-ui. So thats the code:
import React from "react";
import styled from "styled-components";
import ChatIcon from "#mui/icons-material/Chat";
import MoreVertIcon from "#mui/icons-material/MoreVert";
import { Avatar} from "#mui/material";
function Sidebar() {
return (
<Container>
<Header>
<UserAvatar className={"override"} />
<IconsContainer>
<IconButton>
<ChatIcon />
</IconButton>
<IconButton>
<MoreVertIcon />
</IconButton>
</IconsContainer>
</Header>
</Container>
);
}
export default Sidebar;
const Container = styled.div``;
const Header = styled.div`
display: flex;
position: sticky;
top: 0;
background-color: white;
z-index: 1;
justify-content: space-between;
align-items: center;
padding: 15px;
height: 80px;
border-bottom: 1px solid whitesmoke;
`;
const UserAvatar = styled(Avatar)`
height: 60px;
`;
const IconsContainer = styled.div`;
The styled div is working completely fine, but when I import 'Avatar' from #mui and try to add some styling named UserAvatar, it is completely ignoring what I'm writing down.
I think that with mui they have their own version of styled for styled components. https://mui.com/system/styled/
It appears they want you to use it rather than styled-components
import Button from '#mui/material/Button';
import { styled } from '#mui/material/styles';
const CustomButton = styled(Button)({
// your custom styles go here
}) as typeof Button;
see the import from import { styled } from '#mui/material/styles';;

React Router url updates but component does not

Someone plese help, I am unabe to find errors in my code that led the react-router-dom into not working. When I click on any link, URL changes but view doesn't. I've read more than 40 threads and done research but I am unable to find my mistake by my own.
The App.js file
import React, { useEffect } from 'react';
import { BrowserRouter as Router, Switch, Route, Redirect, Link } from 'react-router-dom';
import Header from '../components/Header.component';
import Contact from '../pages/Contact.page';
import DivineShop from '../pages/DivineShop.page';
import Events from '../pages/Events.page';
import Forums from '../pages/Forums.page';
import Home from '../pages/Home.page';
import Sadhanas from '../pages/Sadhanas.page';
let App = (props) => {
useEffect(() => {
document.querySelector('#body').style.backgroundColor = '#eee';
document.querySelector('#body').style.color = '#444';
document.querySelector('#body').style.fontFamily = 'aladin';
document.querySelector('#body').style.fontSize = '18px';
},[])
return (
<>
<Header />
<Router>
<Switch>
<Route path='/' exact component={Home} />
<Route path='/forums' exact component={Forums} />
<Route path='/events' exact component={Events} />
<Route path='/sadhanas' exact component={Sadhanas} />
<Route path='/divineshop' exact component={DivineShop} />
<Route path='/contact' exact component={Contact} />
<Redirect to='/'/>
</Switch>
</Router>
</>
);
}
export default App;
The header Component
import React from 'react';
import styled from 'styled-components';
import Nav from './Nav.component';
const HeroSection = styled.section`
background-image: url(${props => props.backgroundImage});
height: 70vh;
width: 100vw;
`;
const Header = (props) => {
return (
<header>
<Nav />
<HeroSection backgroundImage={props.backgroundImage}/>
</header>
);
}
export default Header
The Nav Component
import React, { useState } from 'react';
import { BrowserRouter as Router, Link } from 'react-router-dom';
import styled from 'styled-components';
import colors from '../configs/colors';
import Logo from '../images/Logo.svg';
import { FaBars } from 'react-icons/fa';
import { GrClose } from "react-icons/gr";
const StyledLink = styled(Link)`
text-decoration: none;
margin-bottom: .5em;
color: ${colors.black};
padding: .5em;
transition: all .3s ease-in;
`;
const StyledMenus = () => (
<Router>
<>
<StyledLink to='/'>Home</StyledLink>
<StyledLink to='/forums'>Forums</StyledLink>
<StyledLink to='/events'>Events</StyledLink>
<StyledLink to='/sadhanas'>Sadhanas</StyledLink>
<StyledLink to='/divineshop'>Divine Shop</StyledLink>
<StyledLink to='/contact'>Contact</StyledLink>
</>
</Router>
);
const MobileNav = styled.nav`
display: flex;
flex-direction: column;
flex-wrap: wrap;
aligh-items: flex-start;
width: 40%;
position: absolute;
left: 1em;
top: 3.5em;
box-shadow: -5px -5px 5px #f9f9f9, 5px 5px 5px #ccc;
border-radius: 20px;
padding: .5em .2em;
display: ${props => props.visibility ? 'flex' : 'none'};
#media screen and (min-width: 550px){
display: none;
}
& *:hover {
padding-left: 2em;
background: ${colors.chineseYellow};
color: ${colors.queenBlue};
}
& *:first-child {
border-radius: 10px 10px 0 0;
}
`;
const HighResNav = styled.nav`
display: flex;
flex-direction: row;
flex: 1 1 70%;
justify-content: space-evenly;
#media screen and (max-width: 550px){
display: none;
}
& * {
border-bottom: 2px solid ${colors.white};
}
& *:hover{
color: ${colors.queenBlue};
border-bottom-color: ${colors.queenBlue};
}
`;
const StyledFaBars = styled(FaBars)`
cursor: pointer;
font-size: 1.2em;
flex: 0 0 auto;
&:hover{
color: ${colors.queenBlue}
}
#media screen and (min-width: 550px){
display: none;
}
`;
const StyledGrClose = styled(GrClose)`
cursor: pointer;
font-size: 1.2em;
flex: 0 0 auto;
&:hover{
color: ${colors.queenBlue}
}
#media screen and (min-width: 550px){
display: none;
}
`;
const NavContainer = styled.section`
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 1em 2em;
justify-content: space-between;
align-items: center;
`;
const Nav = () => {
const [mobileMenuVisibility, setMobileMenuVisibility] = useState(false);
const handleBarClick = () => {
console.log(mobileMenuVisibility);
setMobileMenuVisibility(!mobileMenuVisibility);
}
return (
<NavContainer>
{mobileMenuVisibility ? <StyledGrClose onClick={handleBarClick} /> : <StyledFaBars onClick={handleBarClick} />}
<img src={Logo} alt="Main-Logo" />
<HighResNav>
<StyledMenus />
</HighResNav>
<MobileNav visibility={mobileMenuVisibility ? "true" : undefined}>
<StyledMenus />
</MobileNav>
</NavContainer>
)
}
export default Nav;
Every page have this structure
import React from 'react';
import {withRouter} from 'react-router-dom';
const Contact = () => {
return (
<div>
Hello from contact page
</div>
)
}
export default withRouter(Contact);
Please help
I suspect the issue is that you have two distinct Router components. They are not linked in any way - changing the url in one will not propagate that change to the Switch in the other. Remove the second Router from the StyledMenus component, and move the Header component inside the original Router in App.js.
<Router>
<Header />
<Switch>
<Route path='/' exact component={Home} />
<Route path='/forums' exact component={Forums} />
<Route path='/events' exact component={Events} />
<Route path='/sadhanas' exact component={Sadhanas} />
<Route path='/divineshop' exact component={DivineShop} />
<Route path='/contact' exact component={Contact} />
<Redirect to='/'/>
</Switch>
</Router>

Why my styled component not work with text-decoration?

I'm trying to remove underline for my Link in react by using styled-components
if I use style={{textDecoration: "none"}} it will work but when I use text-decoration: none; in my styled components it won't work:
here is my js code:
import React from "react";
import styled from "styled-components";
import { Link } from "#reach/router";
import { CSSTransition, TransitionGroup } from "react-transition-group";
const StyleNavbarContainer = styled.nav`
background-color: #333333;
width: 100%;
color: #d6d6d6;
position: fixed;
text-align: center;
top: 0;
`;
const AppleLogo = styled.div`
font-size: 20px;
display: inline-block;
`;
const StyleLinkList = styled.ul`
display: inline-block;
`;
const StyledLink = styled(Link)`
padding: 12px 10px;
color: #d6d6d6;
text-decoration: none;
`;
const Navbar = (props) => {
return (
<>
<StyleNavbarContainer>
<AppleLogo>
<i class="fab fa-apple"></i>
</AppleLogo>
<StyleLinkList>
<StyledLink to="/">Mac</StyledLink>
</StyleLinkList>
</StyleNavbarContainer>
</>
);
};
export default Navbar;
add my App.jsx file here is the code:
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Navbar from "./components/Navbar";
function App() {
return (
<div className="App">
<Navbar />
</div>
);
}
export default App;
Need to remove import "bootstrap/dist/css/bootstrap.min.css"; from App.jsx

How do you pass an image to a styled component?

I'm using styled-components in ReactJS and I'm trying to create a component that can take in the background-image as a prop. After some research, I've tried this:
import SpeechBubble1 from '../images/home_images/Speech 1.png';
...
const SpeechBubble = styled.div`
background-image: url(${props => props.background});
`;
...
<SpeechBubble background={SpeechBubble1} />
But it doesn't work. Checking in the browser element window, I can see I'm getting an Invalid property value for background-image.
What am I doing wrong?
Edit:
I also tried doing this, which hasn't worked:
<SpeechBubble style={{background: `url(${SpeechBubble1})`}} />
Make sure you are including a height for the styled component, otherwise, it won't display anything (unless it has children that define its dimensions).
Working example:
components/Container
import styled from "styled-components";
const Container = styled.div`
height: 100vh;
background-image: url(${({ background }) => background});
background-repeat: no-repeat;
background-size: cover;
`;
export default Container;
index.js
import React, { Fragment } from "react";
import { render } from "react-dom";
import reactbg from "./images/reactbg.png";
import Container from "./components/Container";
import GlobalStyles from "./components/GlobalStyles";
import Title from "./components/Title";
const App = () => (
<Fragment>
<GlobalStyles />
<Container background={reactbg}>
<Title>Hello World</Title>
</Container>
</Fragment>
);
render(<App />, document.getElementById("root"));
Index.js
import React from 'react'
import {ProfilePic} from './NavigationElements'
import profileimg from '../../images/profileimg.jpg'
const Navigation = () => {
return (
<NavigationWrapper>
<ProfilePic src={profileimg} alt="" />
</NavigationWrapper>
)
}
export default Navigation
NavigationElements.js
import styled from "styled-components";
export const NavigationWrapper = styled.div`
color: #fff;
`
export const ProfilePic = styled.img`
width: 5vh;
height: 3vh;
margin: 55px;
`
You can use inline styling:
<SpeechBubble style={{background: `url(${SpeechBubble1})`}} />

Resources