Loading screen until Background Img of Component is loaded. React - javascript

I am trying to show a loading screen until a component within a main parent component loads its background image. Most of the articles I found were dealing with images placed directly into the DOM as tags. I have a component that uses a background image.
Here is my Home component which acts as my main container for all components:
class Home extends React.Component {
constructor() {
super();
}
render() {
return (
<div>
<Helmet>
<link id="favicon" rel="icon" href="../SB.png" type="image/x-icon"/>
<title>Snow Bounds</title>
</Helmet>
<CustomNavBar />
<HeroUnit />
<RoadMap />
<TeamFAQ />
<Footer />
</div>
)
}
}
export default Home;
The component in question is the HeroUnit Component which is as follows:
class HeroUnit extends React.Component {
render()
{
return (
<div id="home" className={`fullHeightContainer m-auto bg-primary-hero grad bg-info py-4`} style={{position: "relative"}}>
<Snowfall snowflakeCount={50} color={"rgba(255, 255, 255, .2)"} />
<Container className="h-100">
<div className="heroMainBG h-100" style={{position: "relative",zIndex: 1000}}>
</div>
</Container>
</div>
)
}
}
export default HeroUnit;
How can I make a loading screen show up until the Hero Unit heroMainBg is loaded?
Let me know if you need any other code.. :)

Just use this
class Home extends React.Component {
constructor() {
super();
this.state = {
loaded: false;
}
}
render() {
window.addEventListener("load", event => {
var image = document.querySelector('add the id or className');
var isLoaded = image.complete && image.naturalHeight !== 0;
if(isLoaded)this.setState({loaded:true});
alert(isLoaded); // this tells you whether the image has loaded or not
});
return (
this.state.loaded&&<div>
<Helmet>
<link id="favicon" rel="icon" href="../SB.png" type="image/x-icon"/>
<title>Snow Bounds</title>
</Helmet>
<CustomNavBar />
<HeroUnit />
<RoadMap />
<TeamFAQ />
<Footer />
</div>
)
}
}
export default Home;
You can add a loader when the image is not loaded :
something like this :
!this.state.loaded?<Loader />:Your whole component

Related

Passing props via <Link> tag to separate page

I am making a react site in which I need to pass some props via a Link tag.
I have set up my link tag and have some props contained within there(aboutProps object).
Here is this code.
<Link
to={{
pathname: "/admin-view-full-user-wsa-responses",
aboutProps: {
WSAId: this.props.WSAId
}
}}
>
<button>View Full Details</button>
</Link>
AS you can see I am trying to pass WSAId through to the component.
This is then the component I am trying to pass this through to
import React from "react";
import logo from "../codestone logo.png";
import NavBar from "../PageDetails/Headers/NavBarUsers";
import LogOutButton from "../PageDetails/Buttons/LogOutButton/LogOutButton";
import ProfileButton from "../PageDetails/Buttons/ProfileButton/ProfileButton";
import AdminButton from "../PageDetails/Buttons/AdminButton/AdminButton";
import { Link } from "react-router-dom";
class Home extends React.Component {
constructor(props) {
super(props);
}
// this console logs as undefined
componentDidMount() {
console.log(this.props.location.aboutProps);
console.log(this.props.location.aboutProps);
}
render() {
return (
<>
<Header />
</>
);
}
}
function Header() {
return (
<div className="jumbotron">
<div style={{ textAlign: "right" }}>
<ProfileButton />
<LogOutButton />
<AdminButton />
</div>
<div className="User-Menu"></div>
<img
className="profile-image"
alt="icon"
src={logo}
width="340"
height="60"
/>
</div>
);
}
export default Home;
Any suggestions on how to resolve this are greatly appreciated.
You should be able to pass them using state instead of aboutProps like so:
<Link
to={{
pathname: "/admin-view-full-user-wsa-responses",
state: {
WSAId: this.props.WSAId
}
}}
>
<button>View Full Details</button>
</Link>
And access it with:
this.props.location.state //in a class component
props.location.state //in a functional component

bulma menu toggle in gatsbyjs not working

GatsbyJS beginner here, trying to get the Bulma responsive menu toggle to apply the "is-active" class to the menu (gatsby v2 with gatsby starter netlify cms). all code here: https://github.com/pddew/gatsby-starter-netlify-cms
Currently the toggle button and script tags appear but the button doesn't respond.
There is a working version of this in the gatsby starter business- when I inspect and compare my site with this, I can't spot the error, only that there is no event listener on toggle button, when it seems there should be.
When I inspect the site, the toggle.js script is being called and put in before the closing body tag, and the viewed.
I have tried building and deploying with no luck, clearing caches and swapping the scripts for bulma's suggested code.
Here is the relevant code.
Any help with this greatly appreciated; I'm a bit stuck!
in Layout.js:
import React from 'react' import Helmet from 'react-helmet'
import Navbar from '../components/Navbar' import Footer from '../components/Footer' import './all.sass'
const TemplateWrapper = ({ children }) => ( <div>
<Helmet title="Immediate Start Jobs" />
<Navbar />
<div>{children}</div>
<Footer /> </div> )
export default TemplateWrapper
in Navbar:
<button className="button navbar-burger" data-target="navMenu">
<span />
<span />
<span />
</button>
</div>
<div className="navbar-menu" id="navMenu">
<div className="navbar-start">
<Link className="navbar-item" to="/about">
About
</Link>
<Link className="navbar-item" to="/products">
Products
</Link>
<Link className="navbar-item" to="/blog">
Blog
</Link>
</div>
in html.js
import React from "react"
import PropTypes from "prop-types"
export default class HTML extends React.Component {
render() {
return (
<html {...this.props.htmlAttributes}>
<head>
<meta charSet="utf-8" />
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
{this.props.headComponents}
</head>
<body {...this.props.bodyAttributes}>
{this.props.preBodyComponents}
<div
key={`body`}
id="___gatsby"
dangerouslySetInnerHTML={{ __html: this.props.body }}
/>
{this.props.postBodyComponents}
<script src={__PATH_PREFIX__ + '/js/toggle.js'} />
</body>
</html>
)
}
}
HTML.propTypes = {
htmlAttributes: PropTypes.object,
headComponents: PropTypes.array,
bodyAttributes: PropTypes.object,
preBodyComponents: PropTypes.array,
body: PropTypes.string,
postBodyComponents: PropTypes.array,
}
And my toggle.js, stored in static/js/
document.addEventListener('DOMContentLoaded', function () {
// Get all "navbar-burger" elements
var $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0)
// Check if there are any navbar burgers
if ($navbarBurgers.length > 0) {
// Add a click event on each of them
$navbarBurgers.forEach(function ($el) {
$el.addEventListener('click', function () {
// Get the target from the "data-target" attribute
var target = $el.dataset.target
var $target = document.getElementById(target)
// Toggle the className on both the "navbar-burger" and the "navbar-menu"
$el.classList.toggle('is-active')
$target.classList.toggle('is-active')
})
})
}
})
I'm new to Gatsby myself, but I had to find a way to get my navbar to function. My solution is pretty quick and dirty, but it works. If your building a website with a lot of components that change state, I would suggest using redux and a central store instead. My solution was just having a navbar that handled its own state.
import React, { Component } from 'react'
import Link from 'gatsby-link'
class Navbar extends Component {
state = {
//This sets the state of Bulma elements
navbarIsActive: "navbar-item has-dropdown"
}
//This opens the navbar dropdown
navbarOpenDropdown = () => {
this.setState({
navbarIsActive: "navbar-item has-dropdown is-active"
})
}
//This closes the navbar dropdown
navbarCloseDropdown = () => {
this.setState({
navbarIsActive: "navbar-item has-dropdown"
})
}
render() {
return(
<div>
<nav class="navbar is-transparent" role="navigation" aria-label="dropdown navigation">
<a class="navbar-item">
<h1>Title!</h1>
</a>
<div
class={this.state.navbarIsActive}
onMouseEnter={this.navbarOpenDropdown}
onMouseLeave={this.navbarCloseDropdown}
>
<a class="navbar-link">
Docs
</a>
<div class="navbar-dropdown is-boxed">
<Link to="/">Home</Link>
<Link to="/about">About Us</Link>
<Link to="/blog">Blog</Link>
<hr class="navbar-divider"/>
<div class="navbar-item">
Version 0.7.2
</div>
</div>
</div>
</nav>
<section class="hero">
<div class="hero-body">
<p class="title">
Documentation
</p>
<p class="subtitle">
Everything you need to <strong>create a website</strong> with Bulma
</p>
</div>
</section>
</div>
)
}
}
export default Navbar;
That's just my two pennies' worth: https://nhpcr.codesandbox.io/
src/Navbar.js
import React from 'react';
import PropTypes from 'prop-types';
const NavbarItem = props => (
<a className="navbar-item is-capitalized" href={`#${props.page}`}>
{props.page}
</a>
);
const NavbarBurger = props => (
<button
onClick={props.toggleMenu}
className={`button navbar-burger ${props.active ? 'is-active' : ''}`}
>
<span />
<span />
<span />
</button>
);
export default class Navbar extends React.Component {
state = {
activeMenu: false,
};
toggleMenu = () => {
this.setState({
activeMenu: !this.state.activeMenu,
});
};
render() {
let { pages = [], color } = this.props;
let navbarItems = pages.map(page => <NavbarItem page={page} key={page} />);
return (
<nav className={`navbar is-fixed-top is-${color}`}>
<div className="navbar-brand">
<NavbarItem page="logo" />
<NavbarBurger
active={this.state.activeMenu}
toggleMenu={this.toggleMenu}
/>
</div>
<div
className={`navbar-menu ${this.state.activeMenu ? 'is-active' : ''}`}
>
<div className="navbar-start">{navbarItems}</div>
</div>
</nav>
);
}
}
Navbar.propTypes = {
pages: PropTypes.array.isRequired,
color: PropTypes.string,
};
src/index.js
import React from 'react';
import { render } from 'react-dom';
import Navbar from './Navbar';
import 'bulma/css/bulma.css';
const styles = {
fontFamily: 'sans-serif',
textAlign: 'center',
};
const pages = ['about', 'contact', 'sitemap'];
const App = () => (
<div style={styles}>
<Navbar pages={pages} />
</div>
);
render(<App />, document.getElementById('root'));

React - How to pass props on click text to image

I have this simple app, where I'm looking for a solution to connect the click from the text to the image. Here, the click is not toggeable, just click once and the image is supposed to appear. First, I thought that would make sense to define a state for the image, but honestly I don't think is the best practice.
Which is the best solution for this kind of situation? I aprecciate any provided tips and solutions.
Thank you.
// IMAGE COMPONENT
class Image extends React.Component {
render() {
return (
<div>
<img
alt=""
src="https://media.makeameme.org/created/what-if-I-y0ivox.jpg"
/>
</div>
);
}
}
// TEXT COMPONENT
class Text extends React.Component {
imageClick() {
console.log('click');
}
render() {
return (
<div>
<p onClick={this.imageClick}>If you click me, Morpheus will appear!</p>
</div>
)
}
}
// PARENT COMPONENT
class App extends React.Component {
render () {
return (
<div>
<Text onClick={this.imageClick} />
<Image src={this.props.src} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
Use the parent component to set the visibility of the image.
// IMAGE COMPONENT
class Image extends React.Component {
render() {
return (
<div>
<img
alt=""
src="https://media.makeameme.org/created/what-if-I-y0ivox.jpg"
/>
</div>
);
}
}
// TEXT COMPONENT
class Text extends React.Component {
render() {
return (
<div>
<p onClick={() => this.props.onClick()}>If you click me, Morpheus will appear!</p>
</div>
)
}
}
// PARENT COMPONENT
class App extends React.Component {
state = {
visible : false,
}
toggleVisible = () => this.setState({ visible : !this.state.visible });
render () {
const { visible } = this.state;
return (
<div>
<Text onClick={this.toggleVisible} />
{
visible
&& <Image src={this.props.src} />
}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("#app"));

React - How to show component from an image onClick event in another component?

I have 3 React components:
-Home - need to display the component here when image is
clicked from the Header component
-Header- Contains the image tag that will be clicked to
show the AllSites Component.
-AllSites - component that needs displayed in Home component when Image is
clicked in the Header component.
Header
export class Header extends React.Component<any, any> {
private readonly searchServerUrl = "";
private appButtonElement: HTMLElement;
constructor(props: any) {
super(props);
this.state = { showAppMenu: false };
}
render() {
const { showAppMenu } = this.state;
const { className, navItems, singleColumn, appItems } = this.props;
return (
<header className={className}>
<div className="app-icon">
<button className="nav-button" onClick={() => this.toggleAppMenu()} ref={(menuButton: any) => this.appButtonElement = menuButton}><i className="ms-Icon ms-Icon--Waffle" aria-hidden="true"></i></button>
</div>
***When image is clicked, show the <AllSites/> component in the HomeComponent below.***
<img src="/Styles/Images/logo/loop-logo-white.png" className="nav-logo" onClick={} />
{showAppMenu ? <ApplicationMenu navItems={appItems} targetElement={this.appButtonElement} onDismiss={() => this.onDismiss()} /> : null}
<div className="nav-container"><TopNavigation classNam
e={className} navItems={navItems} singleColumn={singleColumn} /></div>
<div className="search-container">
<SearchBox onSearch={(searchTerm: string) => this.executeSearch(searchTerm)} />
</div>
</header>
);
}
Home
export class HomeComponent extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.state = { navItems: [], appItems: [], singleColumnLayout: false, showAllSites: false };
}
componentDidMount() {
this.checkWidth();
window.addEventListener("resize", this.checkWidth.bind(this));
this.fetchNavigation()
.then(nav => this.setState({ navItems: nav }));
this.fetchAppIcons()
.then(icons => this.setState({ appItems: icons }));
}
componentWillUnmount(): void {
window.addEventListener("resize", this.checkWidth.bind(this));
}
render() {
const { navItems, appItems, singleColumnLayout } = this.state;
return (
<Fabric>
<Header navItems={navItems} appItems={appItems} singleColumn={singleColumnLayout} />
<div className="main-container">
<AlertBar />
<div className="main-content">
<div className="ms-Grid">
When the image tag is clicked, I need to render the <AllSites/> component here
<Hero singleColumn={singleColumnLayout} />
<div className="ms-Grid-row">
<div className="ms-Grid-col ms-sm12 ms-xl4 webpart-container">
<UpcomingEvents />
</div>
<div className="ms-Grid-col ms-sm12 ms-xl4 webpart-container">
<EmployeeNews />
</div>
<div className="ms-Grid-col ms-sm12 ms-xl4 webpart-container">
<div className="ms-Grid-row">
<div className="ms-Grid-col ms-sm12 webpart-container">
<IndustryNews />
</div>
<div className="ms-Grid-col ms-sm12 webpart-container">
<Quote />
</div>
</div>
</div>
</div>
</div>
<Footer navItems={navItems} />
</div>
</div>
</Fabric>
);
}
In the simplest approach you will need a common parent component for your Home and Header that will hold some shared state for them and that will pass a callback to update this state as a prop to Header. In the shared state you need a flag that will be responsible for showing/hiding AllSites component, this flag you will pass as a prop to Home.
You can see a basic example here
If you need a more advanced state management solution, you can check redux library

Render array data in class i react

I have to make a card.
For that I need to make 3 components.
First for Card Header
Second for Card Description and
Third for main Card that will give values to both components.
In my Card class I want to display the array data. I have no idea how to do that.
I believe I should use map() but I do not understand how.
My structure should be like Card header1 with Card description1 then Card header2 with Card description2.
<!Doctype html>
<html>
<head>
<title>React Cards</title>
<link rel="stylesheet" href="screen1.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>
</head>
<body>
<script type="text/jsx">
class Header extends React.Component { render () { return (
<div className='t1'>
<h1>{this.props.text}</h1>
</div>
) } } class CardDesc extends React.Component { render () { return (
<div className='t2' id='this.props.id'>{this.props.text}</div>
) } } class Card extends React.Component { render () { return (
<div className='t3'>
<Header text="this.props.head" />
<CardDesc text="this.props.des" />
</div>
) } } var cardContent = [ {head:'Header one',des:'000'}, {head:'Header two',des:'001'},
{head:'Header three',des:'002'}, {head:'Header four',des:'004'}, {head:'Header
five',des:'005'}, {head:'Header six',des:'006'} ]; ReactDOM.render(
<Card />, document.getElementById('root'))
</script>
<div id="root"></div>
</body>
</html>
When you want to pass a variable as props, don't use quotes, instead use {}, so change:
<Header text="this.props.head"/>
<CardDesc text="this.props.des" />
To:
<Header text={this.props.head}/>
<CardDesc text={this.props.des} />
Now, you can simply render your cards like so:
ReactDOM.render(
<div>
{cardContent.map(cardItem => <Card head={cardItem.head} des={cardItem.des} />)}
</div>
, document.getElementById('root'))
As you can see, a root element (div in this case) is required for the render function.
Another method would be to create a CardList component, and render that, instead of having the map in ReactDOM.render.
I think multiple rendering to the root element is bad idea, you can try create new component like App or whatever, end map your card components into it.
Look at this

Categories

Resources