I have a react component that needs to take in a background image from the parent Play
component, not set in the stylesheet. I'm trying to pass it as a prop to the component, but not sure quite sure how to get this working:
Main component
import React from 'react'
import ReactDOM from 'react-dom'
import DeviceBlock from '/DeviceBlock/DeviceBlock'
const Play = {
init() {
const container = document.getElementById('blocker-container');
if(container) {
ReactDOM.render(
<DeviceBlock
backgroundImage={'background-image-url.png'}
logo={'url-to-logo.png'} />,
container
)
}
}
}
document.addEventListener('DOMContentLoaded', () => {
Play.init()
})
Blocking component imported into above Play component
import React from 'react'
import './DeviceBlock.scss'
function DeviceBlock (props) {
constructor(props) {
super(props)
this.state = {
backgroundImage: backgroundImage,
logo: logo;
}
}
return (
<div className='device-blocking' style={this.state.backgroundImage}>
<div className='container'>
<div className='logo'>
<img src='{{this.state.logo}}' />
</div>
<div className='message'>
<h1>Content</h1>
<a href='/' className='btn btn--primary btn--lg'>Link</a>
</div>
</div>
</div>
)
}
export default DeviceBlock
You should import your background img
import BackgroundImage from '...png'; // Relative Path to BackgroundImage
import Logo from '...png'; // Relative Path to Logo
and in your state
this.state = {
backgroundImage: `url(${BackgroundImage})`,
logo: Logo
};
Also I noticed that your <img>
is wrong
<img src='{{this.state.logo}}' />
Should be
<img src={this.state.logo} />
Also note I saw that you added a constructor inside a function. If you want to create a react component with state you need to make the component a class.
class DeviceBlock extends React.Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
...
}
}
EDIT: This is the updated code for your edit based on passing through props.
import React from 'react'
import ReactDOM from 'react-dom'
import DeviceBlock from '/DeviceBlock/DeviceBlock'
import BackgroundImage from '../url-to-background.png'; // Path to BackgroundImage
import Logo from 'url-to-logo.png'; // Relative Path to Logo
const Play = {
init() {
const container = document.getElementById('blocker-container');
if (container) {
ReactDOM.render(
<DeviceBlock
backgroundImage={BackgroundImage}
logo={Logo}
/>,
container
)
}
}
}
document.addEventListener('DOMContentLoaded', () => {
Play.init()
})
import * as React from 'react'
import './DeviceBlock.scss'
function DeviceBlock (props) {
return (
<div
className='device-blocking'
style={{ backgroundImage: `url(${props.backgroundImage})` }}
>
<div className='container'>
<div className='logo'>
<img src={props.logo} />
</div>
<div className='message'>
<h1>Content</h1>
<a href='/' className='btn btn--primary btn--lg'>Link</a>
</div>
</div>
</div>
);
}
export default DeviceBlock
Note my solution only works if your images are from your own server and processed from webpack and not from another URL.
If the images are from another URL you shouldn't import the URLs and add them directly to the props
<DeviceBlock
backgroundImage="url-to-background.png",
logo="url-to-logo.png"
/>
Style is an object. Try it like this:
style={{backgroundImage: this.state.backgroundImage}}
Further, you cannot have a constructor and use state within a functional component. Either turn your component into a regular react component and keep the state, or have the state part in a regular react component and pass it down as props into the functional component. This is also mentioned in the answer by @Kenneth Truong
To turn it into a regular react component you can do the following:
class DeviceBlock extends React.Component {
constructor(props) {
super(props)
this.state = {
backgroundImage: "url('url-to-background.png')",
logo: "url('url-to-logo.png')";
}
}
render() {
return (
<div className='device-blocking' style={{backgroundImage: this.state.backgroundImage}}>
<div className='container'>
<div className='logo'>
<img src='{{this.state.logo}}' />
</div>
<div className='message'>
<h1>Content</h1>
<a href='/' className='btn btn--primary btn--lg'>Link</a>
</div>
</div>
</div>
)
}
}
You can see it working here: https://codepen.io/anon/pen/zWexzO
UPDATE
Based on the updated question, you can also keep it as a functional component and pass down props:
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
backgroundImage: "url('url-to-background.png')",
logo: "url('url-to-logo.png')";
}
}
render() {
return (
<DeviceBlock
backgroundImage={this.state.backgroundImage}
logo={this.state.logo}/>
)
}
}
const DeviceBlock = (props) => {
return (
<div className='device-blocking' style={{backgroundImage: props.backgroundImage}}>
<div className='container'>
<div className='logo'>
<img src='{{props.logo}}' />
</div>
<div className='message'>
<h1>Content</h1>
<a href='/' className='btn btn--primary btn--lg'>Link</a>
</div>
</div>
</div>
)
}
https://codepen.io/anon/pen/OvdPOQ
The app component is simply demonstrating that you can pass down some dynamic state. You can, of course, render the DeviceBlock
component directly from your Play.init
function like you do in your provided code (then you can just ignore the App component part).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With