My entire component is attached here:
https://gist.github.com/j42/392e63b275e1209ac269
The relevant render method from the component is below, for convenience:
render() {
let className = this.state.active ? 'active hidden-xs' : 'hidden-xs';
return (
<div id="git-flow" className={className}>
<div className="beanstalk-container">
<div className="beanstalk"></div>
<ul className="events">
<TransitionSpring
defaultValue={this.getDefaults()}
endValue={this.getEndValues()}>
{key => {
this.state.people.map(function(person, i) {
let deployFailed = (Math.round(Math.random()*1) <= 0.4),
headline = (deployFailed) ? 'PUSH BLOCKED' : 'PUSHED TO PRODUCTION',
className = (deployFailed) ? 'status negative' : 'status positive',
icon = (deployFailed) ? 'ion-android-close' : 'ion-android-checkmark-circle';
return (<li key={i}
className="person"
style={{
top: `-100px`,
opacity: `1`
}}>
<div className={className}>
<i className={icon}></i>
<div className="label-text">
<h4>{headline}</h4>
<h5><strong>Dec 15th, 2015</strong> — 5:00PM</h5>
</div>
<ul className="notifications">
<li className="notification">
<i className="ion-email-unread"></i>
<span>Group Leader Notified</span>
</li>
</ul>
</div>
<div className="image">
<img src={person.picture.medium} className="img-responsive" />
</div>
</li>);
});
}}
</TransitionSpring>
</ul>
</div>
</div>
);
}
The Problem:
This code runs without any errors, but only renders so far as ul.events. Within that is <noscript data-reactid=".2.0.1.0"></noscript> which leads me to believe React is encountering an error with the JS, and thus silently ignoring the bracketed content.
Everything looks normal to me though... I'm still a bit new to react, so is there something basic I'm overlooking? I just want to have a list of avatars that essentially fadeInDown within a TransitionSpring (so components can be added and removed)...
Thanks for the help!
use React Native Animated.
It's designed to work with React Native.
Related
I have two files that return html fragments. They are identical except for the image. The fact is that the server has different paths to the playlist image and the genre image.
props.items.images[0].url
and
props.items.icons[0].url
because of this, I had to distribute this code to two different files. How could I combine them into one?
const Playlist = props => {
const playListClick = e => {
props.onClick(e.target.title);
}
return (
<section id={props.selectedValue} className="column column__hidden" onClick={playListClick}>
<a className="link__decoration link__track hover__track link__one" href="#">
<div>
{props.items.map((item, idx) =>
<div className="container" key={idx + 1} title={item.id} >
<div className="content__track" title={item.id}>
<img className="img__tarck" title={item.id} src={item.images[0].url}/>
<div className="name" title={item.id}>{item.name}</div>
</div>
</div>)}
</div>
</a>
</section>
);
}
const Genre = props => {
const genreClick = e => {
props.onClick(e.target.title);
}
return (
<section id={props.selectedValue} className="column column__hidden" onClick={genreClick}>
<a className="link__decoration link__track hover__track link__one" href="#">
<div>
{props.items.map((item, idx) =>
<div className="container" key={idx + 1} title={item.id}>
<div className="content__track" title={item.id}>
<img className="img__tarck" title={item.id} src={item.icons[0].url}/>
<div className="name" title={item.id}>{item.name}</div>
</div>
</div>)}
</div>
</a>
</section>
);
You can use a Conditional (ternary) Operator to look if icons exists and if not fallback to using the image. Further assistance is hard due to not knowing the surrounding circumstances.
<img className="img__tarck" title={item.id} src={item.icons ? item.icons[0].url : item.images[0].url}/>
I have a react code (just a snippet, its not a complete code) as shown below which shows the list of programs on the webpage. Line A in the react code below renders all list of program on the webpage.
react code:
const renderPrograms = () => {
return programs.map((program, index)=>{
return (
<a href={program.url} key={index}>
<div className="program" >
<div class="hello-world">{program.name}</div>
</div >
</a>
)
})
}
return(
<div class="parent-div">
<div className ="pqr-xyz">
<h5>Hello World</h5>
</div>
<div className ="abc-def">
<h5>Programs</h5>
{programs && renderPrograms()} {/*Line A*/}
</div>
</div>
)
The above react code renders the following html code at runtime:
<div class="parent-div">
<div className ="pqr-xyz">
<h5>Hello World</h5>
</div>
<div class="abc-def">
<h5>Programs</h5>
<a href="https://www.google.com/">
<div class="program">
<div class="hello-world">TYUV</div>
</div>
</a>
<a href="https://www.twitter.com/">
<div class="program">
<div class="hello-world">SGHS</div>
</div>
</a>
</div>
</div>
Problem Statement:
When Line A does not render anything, my div (<div className ="abc-def">) will look like this at run time:
<div class="abc-def">
<h5>Programs</h5>
</div>
I am wondering what changes I need to make in my react code above so that when Line A doesn't render anything then <div class="abc-def"><h5>Programs</h5></div> should not display on the webpage.
They should be part of the condition:
return(
programs.length > 0 && <div className ="abc-def">
<h5>Programs</h5>
{renderPrograms()}
</div>
)
I changed the condition to check for length, otherwise you'll get a 0 instead of nothing, when empty
Try change this lines:
<div className ="abc-def">
<h5>Programs</h5>
{programs && renderPrograms()} {/*Line A*/}
</div>
into this:
{ programs && (
<div className ="abc-def">
<h5>Programs</h5>
{renderPrograms()} {/*Line A*/}
</div>
) }
Now without programs nothing is displayed.
You can try adding a className like this:
<div className={`abc-def ${programs.length ? "hidden" : ""}`}
Or from the parent componet, you can choose to not render this component with <div>
Instead of trying to hide it using CSS, you also can choose to not render it at all by returning nothing from your function
const RenderPrograms = ({ programs = [] }) => {
if (!programs.length) {
return []
}
return (
<div className="abc-def">
<h5>Programs</h5>
{programs.map((program, index) =>
<a href={program.url} key={index}>
<div className="program">
<div>{program.name}</div>
</div>
</a>
)}
</div>
)
}
ReactDOM.render(
<RenderPrograms />,
document.getElementById('react')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
You can try putting your class in a template string and using a ternary operator to display a certain class when some state value is true.
<div className={`${stateValue ? "name-of-class-with-hide" : "abc-def"}`}>
Here is a complete solution. All you need to do is move the <h5>Programs</h5> inside the condition and modify the condition slightly as shown in following snippet.
<div className ="abc-def">
{
programs.length > 0 && (
<div>
<h5>Programs</h5>
<RenderPrograms programs = {programs}/>
</div>
)
}
</div>
Note that I have modified the RenderPrograms function as well to accept arguments.
Following is a full snippet.
function RenderPrograms(props) {
return props.programs.map((program, index)=>{
return (
<a href={program.url} key={index}>
<div className="program" >
<div className="hello-world">{program.name}</div>
</div >
</a>
)
});
}
function MyApp() {
const programs=[
{name:'program 1', url: 'https://url1.com'},
{name:'program 2', url: 'url2'},
{name:'program 3', url: 'url3'},
];
const programs1 = []; // empty program list
return(
<div class="parent-div">
<h1>When programs list is not empty</h1>
{/*Above line is just for explanation -- you may remove it*/}
<div className ="pqr-xyz">
<h5>Hello World</h5>
</div>
<div className ="abc-def">
{
programs.length > 0 && (
<div>
<h5>Programs</h5>
<RenderPrograms programs = {programs}/>
</div>
)
}
</div>
{/*Below code is just for explanation -- you may remove it*/}
<hr />
<h1>When programs list is empty</h1>
<div className ="pqr-xyz">
<h5>Hello World</h5>
</div>
<div className ="abc-def">
{
programs1.length > 0 && (
<div>
<h5>Programs</h5>
<RenderPrograms programs = {programs1}/>
</div>
)
}
</div>
</div>
)
}
ReactDOM.render(
<MyApp />,
document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
You need to move rendering of programs into RenderPrograms component. Make RenderPrograms component purelu functional and pass data to it via props (Instead of using function).
const RenderPrograms = ({ programs }) => {
let disp = programs.map((program, index) => {
return (
<a href={program.url} key={index}>
<div className="program">
<div class="hello-world">{program.name}</div>
</div>
</a>
);
});
return disp || <span />;
};
then use RenderPrograms to render programs in main component (One with logis for loading programs).
// let programs = [
// {
// url: "test1.com",
// name: "test1"
// },
// {
// url: "test2.com",
// name: "test2"
// }
// ];
let programs = [];
return (
<div className="App">
<div class="parent-div">
<div className="pqr-xyz">
<h5>Hello World</h5>
</div>
<div className="abc-def">
<h5>Programs</h5>
<RenderPrograms programs={programs} />
{/* {programs && renderPrograms()} Line A */}
</div>
</div>
</div>
);
You can play around with this sandbox
Here's what I've have so far - Full working view https://codesandbox.io/s/hungry-elbakyan-v3h96
Accordion component:
const Accordion = ({ data }) => {
return (
<div className={"wrapper"}>
<ul className={"accordionList"}>
{data.map((item) => {
return (
<li className={"accordionListItem"} key={item.title}>
<AccordionItem {...item} />
</li>
);
})}
</ul>
</div>
);
};
const AccordionItem = ({ content, title }) => {
const [state, setState] = useState({
isOpened: false
});
return (
<div
className={cn("accordionItem", state.isOpened && "opened")}
onClick={() => setState({ isOpened: !state.isOpened })}
>
<div className={"lineItem"}>
<h3 className={"title"}>{title}</h3>
<span className={"icon"} />
</div>
<div className={"inner"}>
<div className={"content"}>
<p className={"paragraph"}>{content}</p>
</div>
</div>
</div>
);
};
When I click on the accordion item nothing happens. I can see the content appears in inspect and the state changes as expected but it doesn't slide down. Did I miss something in my css or component?
Here is what I was able to achieve. You may not like it completely(animations). But things seems sorted
https://codesandbox.io/s/relaxed-babbage-2zt4f?file=/src/styles.css
props name was not right for accordion body
and styles need to be changes once the accordion is in open state.
You need to add or remove the className inner when state.isOpen so you can see your content
Can anyone explain what's going on here?
On the index page referenced below there is a section where I source data from a WordPress API to generate the four most recent posts from a client. When running in develop mode with Gatsby, the website is presented fine, but when I upload the website to Netlify and build it out, the data disappears and leaves nothing more than an empty set of p tags.
When I go into development tools and step through breakpoints, I notice that the data in question appears on the website, but then disappears once the webpack fires and the modules are bundled. It's almost as if this data is getting overwritten. When I navigate away from this page on the same website, and then return, the p tags HAVE the data in question. I'm assuming the webpack overwrites the initial code, and then when I come back to the page the webpack has already fired so it loads the information fine? How do I work around this? Excuse me if this is a silly/obvious question.
Full code in reference:
import React from "react"
import { Link, graphql, useStaticQuery } from 'gatsby'
import Layout from '../components/layout'
import indexStyles from '../components/modules/index.module.css'
import Carousel from 'nuka-carousel'
import header1 from '../img/header1.jpg'
import header2 from '../img/header2.jpg'
import header3 from '../img/header3.jpg'
const IndexPage = () => {
const data = useStaticQuery(graphql`
query {
allWordpressPost (sort: {fields:date, order:DESC}) {
edges {
node {
title
slug
excerpt
date(formatString:"MMMM DD, YYYY")
}
}
}
}
`)
return (
<Layout>
<div className={indexStyles.indexCarousel_container}>
<Carousel
autoplay={true}
autoplayInterval={5000}
pauseOnHover={false}
wrapAround={true}
renderCenterLeftControls={({ previousSlide }) => (
<button onClick={previousSlide} className={indexStyles.indexCarousel_button}><i className="fas fa-arrow-left"></i></button>
)}
renderCenterRightControls={({ nextSlide }) => (
<button onClick={nextSlide} className={indexStyles.indexCarousel_button}><i className="fas fa-arrow-right"></i></button>
)}>
<div className={indexStyles.indexCarousel_slideContainer}>
<img src={header1} alt="Pencil case with cat, heart, and cupcake design."></img>
<div>
<h2>Shop</h2>
</div>
</div>
<div className={indexStyles.indexCarousel_slideContainer}>
<Link to="/blog"><img src={header2} alt="Notepad next to a cup of coffee."></img></Link>
<div>
<h2>Blog</h2>
</div>
</div>
<div className={indexStyles.indexCarousel_slideContainer}>
<img src={header3} alt="Colorful pencil cases."></img>
<div>
<h2>Cute Castle VIP</h2>
<p>Save 20%!</p>
</div>
</div>
</Carousel>
</div>
<h1 className={indexStyles.indexHeader}>Latest Posts</h1>
<div className={indexStyles.indexPost_container}>
<div className={indexStyles.indexPost_container}>
{data.allWordpressPost.edges.map((edge, i) => {
if (i < 4) {
return (
<div className={indexStyles.index_post}>
<h2><Link to={`/blog/${edge.node.slug}`} className={indexStyles.post_title} dangerouslySetInnerHTML={{ __html: edge.node.title }}></Link></h2>
<p className={indexStyles.post_date}>{edge.node.date}</p>
<p className={indexStyles.post_excerpt} dangerouslySetInnerHTML={{ __html: edge.node.excerpt }} />
<p><Link to={`/blog/${edge.node.slug}`} className={indexStyles.post_link}>Read more</Link></p>
</div>
)
}
})}
</div>
</div>
</Layout >
)
}
export default IndexPage
The section of code that disappears and reappears:
<div className={indexStyles.indexPost_container}>
<div className={indexStyles.indexPost_container}>
{data.allWordpressPost.edges.map((edge, i) => {
if (i < 4) {
return (
<div className={indexStyles.index_post}>
<h2><Link to={`/blog/${edge.node.slug}`} className={indexStyles.post_title} dangerouslySetInnerHTML={{ __html: edge.node.title }}></Link></h2>
<p className={indexStyles.post_date}>{edge.node.date}</p>
<p className={indexStyles.post_excerpt} dangerouslySetInnerHTML={{ __html: edge.node.excerpt }} />
<p><Link to={`/blog/${edge.node.slug}`} className={indexStyles.post_link}>Read more</Link></p>
</div>
)
}
})}
</div>
</div>
A link to the Netlify project.
https://zealous-engelbart-509321.netlify.com/
Thanks in advance for your help!
I have an image gallery where I loop trough image objects and I want to pass the i to my onClick function. This is my image gallery code:
<div className="gallery clearfix">
{ block.gallery.map((item, i) => (
i < 1 ?
<div className="gallery-image" key={i} onClick={this.toggle}>
<a href='' className="inner">
<img src={item.images.thumbnail_sm} alt={block.title} srcSet={`${item.images.thumbnail_md} 1x, ${item.images.thumbnail_lg} 2x`} className="img-fluid image"/>
</a>
</div>
: null
))}
<div className="gallery-thumbs">
<div className="row">
{ block.gallery.map((item, i) => (
i > 0 && i < (limit + 1) ?
<div className="gallery-item" key={i} onClick={this.toggle}>
<a href='' className="inner">
<img src={item.images.thumbnail_sm} alt={block.title} srcSet={`${item.images.thumbnail_md} 1x, ${item.images.thumbnail_lg} 2x`} className="img-fluid image" title="" />
{ block.gallery.length > (limit + 1) && i == limit ?
<div className="img-overlay">
<span className="img-indicator">{ block.gallery.length - (limit + 1) }+ <span className="hidden-xs">Foto's</span></span>
</div>
: null
}
</a>
</div>
: null
))}
</div>
</div>
</div>
And this is my reactstrap modal where I want to show the image which is clicked:
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalBody>
<img src={block.gallery[this.state.clickedImage].item.images.thumbnail_lg}/>
</ModalBody>
</Modal>
And here is the toggle function where I want to pass the clickedImage id:
toggle(id) {
this.setState({
clickedImage: id,
modal: !this.state.modal
});
}
For best practice, I don't suggest binding within onClick, that cause it invoke bind every time when it's clicked. if you are using ES6, instead you should bind it in constructor:
Class MyComponent extends React.Component {
constructor(props){
super(props);
this.toggle = this.toggle.bind(this);
}
}
and
<div className="gallery-item" key={i} onClick={(i) => this.toggle(i)}></div>
UPDATE: like comments say. this is actually is not the best way, the best way is not to create new function and attach events with every render, which means it should be just
<div className="gallery-item" key={i} onClick={this.toggle}></div>
but since you need to pass the id, the best bet would be refactor it into smaller components like <GalleryItem> and pass the id by props
Worth to read: this
UPDATE: Also please look at comments, using dataset.index and data-index is even better