React - How to pass props on click text to image - javascript

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"));

Related

Loading screen until Background Img of Component is loaded. React

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

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 Input text now being shown

I'm trying to create a composed input text (joining 4 input components) but i'm not being able.
Everything seems to be OK and the only way I Have been able to show the input text is placing it in the render of the main React component (cardform). In the DOM explorer (chrome) the only componet I an empty cardNumberFullField
This is the HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://unpkg.com/react#15/dist/react.min.js"></script>
<script src="https://unpkg.com/react-dom#15/dist/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel" src="script.js"></script>
</body>
</html>
This is the JS:
class CardForm extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<cardNumberFullField />
</div>
)
}
}
function cardNumberFullField() {
return (
<div>
<cardNumberInputField inputName="0" />
<cardNumberInputField inputName="1" />
<cardNumberInputField inputName="2" />
<cardNumberInputField inputName="3" />
</div>
)
}
function cardNumberInputField(props) {
return (
<div>
<input id={props.inputName} name={props.inputName} type="text" />
</div>
)
}
// Main render
ReactDOM.render(<CardForm />, document.getElementById("root"))
React custom components always needs to be in Capitalized. So cardNumberFullField should be CardNumberFullField, cardNumberInputField should be CardNumberInputField
Check Specifying The React Element Type.
The first part of a JSX tag determines the type of the React element.
Capitalized types indicate that the JSX tag is referring to a React
component. These tags get compiled into a direct reference to the
named variable, so if you use the JSX expression, Foo must be
in scope.
class CardForm extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<CardNumberFullField />
</div>
);
}
}
function CardNumberFullField() {
return (
<div>
<CardNumberInputField inputName="0" />
<CardNumberInputField inputName="1" />
<CardNumberInputField inputName="2" />
<CardNumberInputField inputName="3" />
</div>
);
}
function CardNumberInputField(props) {
return (
<div>
<input id={props.inputName} name={props.inputName} type="text" />
</div>
);
}
// Main render
ReactDOM.render(<CardForm />, document.getElementById("root"));
<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>
<div id="root"></div>

React: how can I import another class to use when using React in HTML

I added react to an HTML page. With this approach, how can I write a class above my App class and import it to use within Class?
class Header extends React.Component
above my App class but it I keep getting an error:
super expression must be null or a function
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css" media="screen" />
</head>
<body>
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script type="text/babel">
class App extends React.Component {
componentDidMount() {}
render() {
return (
<div className="">
</div>
);
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
);
</script>
</body>
</html>
The class would be just another React Component, so you can just render it as you would any:
class Header extends React.Component {
render() {
return (
<h1>My Custom Header</h1>
)
}
}
class App extends React.Component {
componentDidMount() {
}
render() {
return (
<div className="">
<Header/>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
That said, you might just want to use functional components in such (stateless) cases.

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