Reputation: 3151
I need to pass in an Image object from the page down to a component which calls a component for each image.
Home() -> ThreePanel() -> Panel()
From my understanding of props, this should be possible with the passing of props from ThreePanel to Panel.
But there is an error:
Server Error Error: Image is missing required "src" property. Make sure you pass "src" in props to the
next/image
component. Received: {"height":"170em"}
This is what is the source of the error is. I need to specify a specific object. But as a template, I'd like to use a variable.
<Image src={props.cardData.icon} // <-- Doesn't let me specify generic variable
height="170em"/>
<Image src={props.cardData.icon.firstImage}
height="170em"/>
I'm using Next JS.
Here's the full code below:
import ThreePanel from '../components/threePanel'
import firstImage from '../public/images/one.png'
import secondImage from '../public/images/two.png'
import thirdImage from '../public/images/three.png'
export default function Home() {
return (
<ThreePanel
panelOne = {{ icon: {firstImage}, name: "First" }}
panelTwo = {{ icon: {secondImage}, content: "Second" }}
panelThree = {{ icon: {thirdImage}, content: "Third" }}>
</ThreePanel>
)
}
import Panel from '../components/panel'
export default function ThreePanel(props) {
return (
<Grid container>
<Grid item>
<Panel cardData={props.firstImage.icon}></Panel>
</Grid>
<Grid item>
<Panel cardData={props.secondImage.icon}></Panel>
</Grid>
<Grid item>
<Panel cardData={props.thirdImage.icon}></Panel>
</Grid>
</Grid>
)
}
import Image from 'next/image'
export default function Panel(props) {
return (
<Image src={props.cardData} // <-- Doesn't let me specify generic variable
height="170em"/>
)
}
Upvotes: 2
Views: 4354
Reputation: 202605
props.firstImage.icon
isn't defined in the ThreePanel
component as the image was passed as panelOne={{ icon: {firstImage}, name: "First" }}
. This means the child component would need to access props.panelOne.icon.firstImage
to get to the image. This may work if each Panel
component is passed the correctly nested property.
<Panel cardData={props.panelOne.icon.firstImage} />
<Panel cardData={props.panelTwo.icon.secondImage} />
...etc...
As you can see, each child panel needs to know which panel it is, but also needs to know what the image property was named. This isn't ideal.
You should strive to pass consistently named props down to "repeated" children as each "instance" won't be aware which dynamic prop they should access. In this case it's the value passed that is dynamic, not the prop key.
Home
Pass the dynamic image values on a standard prop, like icon
.
import firstImage from '../public/images/one.png';
import secondImage from '../public/images/two.png';
import thirdImage from '../public/images/three.png';
export default function Home() {
return (
<ThreePanel
panelOne={{ icon: firstImage, name: "First" }}
panelTwo={{ icon: secondImage, content: "Second" }}
panelThree={{ icon: thirdImage, content: "Third" }}
/>
)
}
ThreePanel
Access the "dynamic" panel prop to pass the specific panel prop object to each Panel
component. Now the intermediate ThreePanel
component doesn't need to know much of the deeper nested values, it knows to pass 1 of 3 panel prop objects to it's 3 panel children.
export default function ThreePanel(props) {
return (
<Grid container>
<Grid item>
<Panel cardData={props.panelOne} />
</Grid>
<Grid item>
<Panel cardData={props.panelTwo} />
</Grid>
<Grid item>
<Panel cardData={props.panelThree} />
</Grid>
</Grid>
)
}
Panel
Now the passed carData
prop will be the specific image that was passed from grandparent/ancestor component. Notice here that each individual panel doesn't know which of the 3 panels it is, but it knows it has an image icon prop to access.
export default function Panel(props) {
return (
<Image
src={props.cardData.icon}
height="170em"
/>
)
}
Upvotes: 1
Reputation: 974
In threePanel.js the panel props should be cardData=props.panelOne, isnt it? Instead of props.cardOne
Upvotes: 0