Trying to set image as div background inside map function in React.js project, but I can't access post.featured_image_src outside map function and set as background in the divStyle variable:
class Archive extends Component {
render() {
let allPosts = DataStore.getAllPosts();
let pageData = DataStore.getPageBySlug('archive');
let acf = pageData.acf;
const divStyle = {
backgroundImage: 'url(' + post.featured_image_src + ')'
}
return (
<div>
<h1>{pageData.title.rendered}</h1>
<div className="post-container">
<div className="post-wrapper">
{allPosts.map((post, i) => {
return (
<div className="post" key={i}>
{post.featured_image_src
? <a href={post.link}><div style={divStyle}/></a>
: null}
<h3 className="post-title"><a href={post.link} dangerouslySetInnerHTML={{__html:post.title.rendered}} /></h3>
</div>
)
}
)}
</div>
</div>
</div>
);
}
}
Any tips would be oh so lovely .. <3
The problem is that post is not defined when you try to access it to define styles
const divStyle = {
backgroundImage: 'url(' + post.featured_image_src + ')'
}
You could move have this logic as a function
const divStyle = (src) => ({
backgroundImage: 'url(' + src + ')'
})
return (
<div>
<h1>{pageData.title.rendered}</h1>
<div className="post-container">
<div className="post-wrapper">
{allPosts.map((post, i) => {
return (
<div className="post" key={i}>
{post.featured_image_src
? <a href={post.link}><div style={divStyle(post.featured_image_src)}/></a>
: null}
<h3 className="post-title"><a href={post.link} dangerouslySetInnerHTML={{__html:post.title.rendered}} /></h3>
</div>
)
}
)}
</div>
</div>
</div>
);
For obvious reasons you cannot use the variable before its defined.
You can rather replace <div style={divStyle}/> with:
<div style={ backgroundImage: "url(" + post.featured_image_src + ")" } />
OR, as suggested by #Shubham, use a method that will return the desired style object:
const divStyle = (imgSrc) => ({
backgroundImage: `url(${imgSrc})`
})
In render:
<div style={this.divStyle(post.featured_image_src)}/>
{ post.featured_image_src
? <a href={post.link}>
<div className="post-img" style={{backgroundImage: `url(${post.featured_image_src})`}}/>
</a>
: null
}
Related
Hi I am trying to implement a modal with slideshow for next images. I am using unsplash api to fetch images.
The problem I am facing is whenever I am trying to click a random image in a grid, it shows only the first image in Modal.
This is my implementation for setting up the images and modal functionality. I am using the react-modal package for setting up my Modal.
imageList = Array of objects containing image data
url = An object containing image url.
export default function Images({ imageList, url, id }) {
const [modalIsOpen, setModalIsOpen] = useState(false);
const [current, setCurrent] = useState(0);
const length = imageList.length;
function openModal() {
setModalIsOpen(true);
}
function closeModal() {
setModalIsOpen(false);
}
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 1);
};
const prevSlide = () => {
setCurrent(current === 0 ? length - 1 : current - 1);
};
if (!Array.isArray(imageList) || imageList.length <= 0) {
return null;
}
return (
<div>
<img onClick={openModal} key={id} src={url.urls.thumb} alt='' />
<Modal
ariaHideApp={false}
closeTimeoutMS={200}
style={customStyles}
isOpen={modalIsOpen}
onRequestClose={closeModal}
contentLabel='Image modal'
>
<AiOutlineArrowLeft
className='left-arrow'
onClick={prevSlide}
/>
<AiOutlineArrowRight
className='right-arrow'
onClick={nextSlide}
/>
{imageList.map((image, id) => {
return (
<div
className={
id === current ? 'slide active' : 'slide'
}
key={id}
>
{id === current && (
<img
alt=''
className='image'
src={image.urls.small}
/>
)}
</div>
);
})}
</Modal>
</div>
);
}
Thanks in advance for the help.
You should set the current-image-index by clicking the img.
<img onClick={()=>openModal(id)=} key={id} src={url.urls.thumb} alt='' />
function openModal(id) {
setCurrent(id);
setModalIsOpen(true);
}
or use the id / index from the props
const [current, setCurrent] = useState(id);
set current by passing image id
<img onClick={()=>openModal(id)} key={id} src={url.urls.thumb} alt='' />
function openModal(id) {
setCurrent(id);
setModalIsOpen(true);
}
I'm trying to render a card with a background image, however, the image is not showing up with this current syntax. I've tried substituting ${this.props.flat.imageUrl} for src and that doesn't work. The price and flat name are rendering though. Not sure where to go from here.
render() {
const src = this.props.flat.imageUrl;
return (
<div
className="card" style={{
backgroundImage: `url(('${this.props.flat.imageUrl}')`
}}
>
<p className="card-category">{this.props.flat.price}</p>
<p className="card-description">{this.props.flat.name}</p>
</div>
);
}
You seem to have an extra ( in your backgroundImage property. I would also suggest moving your style out of the return for better readability like so:
export default function App() {
const src = 'https://png.pngtree.com/element_our/png/20180928/beautiful-hologram-water-color-frame-png_119551.jpg';
const style = {backgroundImage: `url(${src})`}
return (
<div
className="card" style={style}
>
<p className="card-category">$23</p>
<p className="card-description">Some name here</p>
</div>
);
}
Inline-Style is not properly applied to the backgroundImage. Try this;
backgroundImage: `url(${this.props.flat.imageUrl})`
The curly braces inside backgroundImage property are wrong. Please try below code.
render() {
const src = this.props.flat.imageUrl;
return (
<div
className="card" style={{
backgroundImage: "url(" + src + ")"
}}
>
<p className="card-category">{this.props.flat.price}</p>
<p className="card-description">{this.props.flat.name}</p>
</div>
);
}
idk why background image style is not working on react,
{
musics && musics.map((name, i) => {
console.log(typeof name.imageURL);
return(
<Fragment key = {i}>
<div className = "music-preview-box">
<div className = "user-musics-content">
<div id = "album-cover" style ={{backgroundImage: "url("+name.imageURL+")"}}>
</div>
</div>
</div>
</Fragment>
)
}
}
when i console log it shows the url, when i put the real url instead of name.imageURL it works. but when i only keep name.imageURL it doesnt work
Try to double quotes the url("...")
<div id = "album-cover" style={{ backgroundImage:`url("${name.imageURL}")` }}></div>
What about -
<div id = "album-cover" style ={ { backgroundImage: "url('+name.imageURL+')" } }>
or
<div id = "album-cover" style ={ { backgroundImage: `url("${name.imageURL}")` } }>
I am trying to use classNames to replace the conditional below in one line.
My problem is that i am not sure what is the right way to write the code because of the div etc...
I have the codes below :
conditional
const { pageTitle, removeTitle = false } = props; # destructuring
let result;
if(removeTitle){
result = <div className="header-without-title">{pageTitle}</div>;
} else {
result = <div className="header-with-title">{pageTitle}</div>;
}
return (<div className="result-title">{result});
};
If the div did not exist, i could write something like this...
const result = classNames({"header-without-title": removeTitle, "header-title": !removeTitle});
But i am not sure now that I have the div , I would appreciate some help here...
A solution outside of JSX would be very helpful
return (
<div className="result-title">
<div className={`header-${removeTitle ? 'without-title' : 'with-title'}`}>{pageTitle}</div>
</div>
);
or with use https://github.com/JedWatson/classnames
return (
<div className="result-title">
<div className={classNames({ 'header-without-title': removeTitle, 'header-with-title': !removeTitle })}>
{pageTitle}
</div>
</div>
);
EDIT:
A solution outside of JSX
const result = (
<div className={classNames({ 'header-without-title': removeTitle, 'header-with-title': !removeTitle })}>
{pageTitle}
</div>
);
return (
<div className="result-title">
{result}
</div>
);
You can just inline classNames function
const { pageTitle, removeTitle = false } = props;
const result = classNames({"header-without-title": removeTitle, "header-title": !removeTitle});
return (
<div className="result-title">
<div className={result}>
{pageTitle}
</div>
</div>);
);
There are several answers to this. Depends of each case
Ternary between two classes in React:
<div className={`header-${removeTitle ? 'without-title' : 'with-title'}`}>
Ternary between class or null in React Javascript:
<div className={removeTitle ? 'without-title' : null}>
Ternary between render class or not in React Javascript and Typescript:
<div className={...(removeTitle ? { className: 'without-title' } : {})}>
I have the following code.
var ImageList = React.createClass({
getComponent: function(index){
console.log(index);
},
render: function() {
var results = this.props.data;
return (
<div className="row">
{results.map(function(result) {
return(
<a className="th medium-3 columns" href="#" onClick= {this.getComponent.bind(this, 1)}>
<img alt="Embedded Image" key={result.id} src={"data:" + result.type + ";" + "base64," + result.image} />
</a>
)
})}
</div>
);
}
});
The second return function basically loops an array of images and shows them. I wanted an OnClick event when clicked should trigger the getComponent method. However if the OnClick event is within the array loop it throws the following error:
Uncaught TypeError: Cannot read property 'getComponent' of undefined.
However if i use the same code and just add the onClick even after the looping function like below:
var ImageList = React.createClass({
getComponent: function(index){
console.log(index);
},
render: function() {
var results = this.props.data;
return (
<div className="row">
{results.map(function(result) {
return(
<img alt="Embedded Image" key={result.id} src={"data:" + result.type + ";" + "base64," + result.image} />
)
})}
<a className="th medium-3 columns" href="#" onClick= {this.getComponent.bind(this, 1)}>
</div>
);
}
});
Ends up working fine. But since i need to keep a unique id for each image only then can i complete the remaining function of getComponent the second method isn't much use for me. Hence is there any way to make it work within the Loop?
Your scope changes within the .map method:
{results.map(function(result) {
// `this` is different inside this anonymous function
})}
What you want to do is either use ES6' fat arrow syntax, which automatically creates an anonymous function with the same scope, or store the current scope of this in a variable:
ES6 Fat Arrow (read more here):
render: function() {
var results = this.props.data;
return (
<div className="row">
{results.map( (result) => {
return(
<a className="th medium-3 columns" href="#" onClick={that.getComponent.bind(that, 1)}>
<img alt="Embedded Image" key={result.id} src={"data:" + result.type + ";" + "base64," + result.image} />
</a>
)
})}
</div>
);
}
});
Note that you'll need a transpiler — such as babel.io — to change this into ES2015 which browsers currently understand to run. This is considered "best practice", as ES6/7 brings better functionality to JS.
Storing a reference to this:
render: function() {
var results = this.props.data,
that = this;
return (
<div className="row">
{results.map(function(result) {
return(
<a className="th medium-3 columns" href="#" onClick={that.getComponent.bind(that, 1)}>
<img alt="Embedded Image" key={result.id} src={"data:" + result.type + ";" + "base64," + result.image} />
</a>
)
})}
</div>
);
}
});
You can use ES6 arrow functions to automatically preserve this context:
results((result) => {
...
})
or just pass this as second param to the map:
results(function(result) {
...
}, this)