I wanted to inquire about something. I am trying to display staff images, bio, etc.
My query is like so:
const data = useStaticQuery(graphql`
query {
allContentfulStaff {
edges {
node {
staffBio {
staffBio
}
staffImages {
id
gatsbyImageData
description
}
staffOneLine
}
}
}
}
`);
My map function is like so:
return (
<>
<h1>Our Rockin' Staff</h1>
{data.allContentfulStaff.edges.map((node, index) => {
console.log(data.allContentfulStaff);
return (
<div>
<GatsbyImage
key={``}
image={node.gatsbyImageData}
alt={node.description}
/>
{node.staffOneLine}
</div>
);
})}
</>
);
I receive the data from
{node.staffOneLine }, but nothing for the images.
When I console log {data.allContentfulStaff}, I see an array of images that I will attach.
However, I am getting an error which I will also attach… but none of my other queries / functions where I am grabbing images in the same manner are giving me this error and they look relatively similar. I also did not need the image prop in my components as I am using
<GatsbyImage />
Curious if you have any ideas?
node is an array/set of images as staffImages (of 1 position only) is, so you'll need to add directly to each position like:
<GatsbyImage image={item.node.staffImages[0].gatsbyImageData} alt={ 'staff image' } />
You are looping the data correctly as you pointed out with the console.log() but as you can see there, and because your data structure, staffImages is an array of one position (always) that holds the gatsbyImageData so you need to access directly to that position.
The getImage() function discussed in comments is completely optional and it won't change the fact that an image is showing/not showing at all. As you can see in the docs:
import { getImage } from "gatsby-plugin-image"
const image = getImage(data.avatar)
// This is the same as:
const image = data?.avatar?.childImageSharp?.gatsbyImageData
Related
I've have started seeing the following notice in the web developer console when editing posts in Gutenberg:
wp.blockEditor.RichText multiline prop is deprecated since version 6.1 and will be removed in version 6.3. Please use nested blocks (InnerBlocks) instead.
I am unsure how I would go about converting my custom static Gutenberg block that currently uses <RichText> with the multiline property into a <div> with <InnerBlocks /> that still honor the original functionality that I built. This is a simplified example of what the edit() function currently looks like for the block:
edit: ( props ) => {
const blockProps = useBlockProps( { className: 'custom-cta p-0 mb-0' } );
const { attributes: { blurb }, setAttributes, className, isSelected } = props;
return (
<div { ...blockProps }>
<RichText
tagName="div"
multiline="p"
className="custom-cta__blurb w-100"
translate-name="blurb"
onChange={ value => setAttributes( { blurb: value } ) }
placeholder={ __( 'Subtext goes here (optional)', 'hello-tools' ) }
value={ blurb }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
focusOnInsert={ false }
/>
</div>
);
}
This might come fairly close to what you are looking for. Try it - you might have to add some more attributes/settings and possibly CSS to get the exact result you are looking for.
This will not be able to replace your current block - so what I mean is, it is not backwards compatible, since it is a totally new block.
/**
* #see ./edit.js
*/
edit: () => {
// define which blocks to show when the block gets inserted
const TEMPLATE = [['core/paragraph']];
// define what blocks are allowed to be used
let allowedBlocks = ['core/paragraph'];
const blockProps = useBlockProps({className: 'my-custom-class'});
return (
<div {...blockProps}>
<div className={'custom-cta__blurb w-100'}>
<InnerBlocks
allowedBlocks={allowedBlocks}
template={TEMPLATE}
// false will let the user add and move the blocks
templateLock={false}
/>
</div>
</div>
)
}
```
I cant contribute to the discussion under the solution above, but I believe Frizzant is mistaken. Wordpress has included a solution in their list item block on GitHub, but I do not understand how to implement it.
I have a sidebar where it is possible to change the background of the sidebar as a background, I store pictures in the object, everything worked well for me until I decided to add a second property "color" inside the object, that is, in addition to changing the background, the color of the text also changes. it looks like this
I think that the essence is clear, but as I mentioned earlier, the problems started when I decided to add a second property, that is, the color of the text
The problem is that the color property does not work for me, that is, it works, but in this case the sidebar background does not work
My object looks very simple
import Bg from "../../SideBar/Background/mac.jpg"
import Pink from "../../SideBar/Background/pink.jpg"
import Anapa from "../../SideBar/Background/anapa.jpg"
const SideBarBackgrounds = [
{
SideBarWallpaper: Bg,
color: "red",
},
{
SideBarWallpaper: Pink,
color: "green",
},
{
SideBarWallpaper: Anapa,
color: "yellow",
},
].map((item) => {
return {
SideBarWallpaper: item.SideBarWallpaper,
color: item.color,
}
}
)
export default SideBarBackgrounds;
That is, I import the picture and apply it as the value for the SideBarWallpaper properties then create a second property named color and apply the string as the color
Then I use local storage to save the user changes.
export const CounterContext = createContext([]);
export default function ThemeDoc(props) {
const [SideBarBackground, SetSideBarBackground] = useState(JSON.parse(localStorage.getItem("BgKey")));
useEffect(() => {
localStorage.setItem("BgKey", JSON.stringify(SideBarBackground));
})
const ChangeSideBarWallpaper = (SideBarWallpaper) => {
localStorage.setItem('BgKey', JSON.stringify(SideBarWallpaper));
SetSideBarBackground(SideBarWallpaper);
}
return (
<div className="page-wrapper chiller-theme toggled">
<CounterContext.Provider value={{
SideBarWallpaperValue: [SideBarBackground, SetSideBarBackground],
}}>
<SideBar ChangeSideBarWallpaper={ChangeSideBarWallpaper} SideBarPageContent={SideBarPageContent} {...props} />
</CounterContext.Provider>
</div>
);
}
As you can see, I use React Context since I have a lot of themes and I import them in many files, in this case I deleted everything personal and left only the code that belongs to the background of the sidebar
Then I have a component called SideBarWallpaperContainer where I import my object, create a loop using a map, process each property from the object and finally import the SideBarWallpaperContainer component inside the SideBarModal component
export default function SideBarWallpaperContainer(props) {
const SideBarWallpaperList = SideBarBackgrounds.map((theme, index) => {
return (
<img key={index} width={"70"} height={"55"} src={theme.SideBarWallpaper}
className={"SideBar_Appearance_Select_Icon"}
onClick={() => props.ChangeSideBarWallpaper(theme.SideBarWallpaper)} alt={"Select Theme"}/>
);
})
return (
<>
{SideBarWallpaperList}
</>
);
}
SideBarModal.jsx
const DraggableDialog = (props) => {
...
return(
<SideBarWallpaperContainer {...props} />
...
);
}
Through props, I get the ChangeSideBarWallpaper method to change the background and color
And the color for the sidebar text I get using useContext it looks like this
SideBarMenu.jsx
export default function SideBarMenu(props) {
const {SideBarWallpaperValue} = React.useContext(CounterContext);
const [SideBarWallpaperTheme,] = SideBarWallpaperValue;
const SideBarWallpaperStyle = SideBarWallpaperTheme;
return(
<Link
style={{ color: SideBarWallpaperStyle && SideBarWallpaperStyle.color,}}>{item.name}
</Link>
);
}
Now when you roughly understand how all the logic works, I want to explain the problem. The problem is that either the sidebar color or the background does not work for me, please pay attention to the method
props.ChangeSideBarWallpaper (theme.SideBarWallpaper)}
When I use theme.SideBarWallpaper as a parameter inside the ChangeSideBarWallpaper method, only the background works for me and not the color, and this is of course logical, then I tried to apply 2 parameters, the color and the background, it looked like this
onClick={() => props.ChangeSideBarWallpaper(theme.SideBarWallpaper, theme.color)}
But in this case, only the background also worked and the only solution that remained for me to transfer the entire value, it looked like this
onClick={() => props.ChangeSideBarWallpaper(theme)}
And then I was surprised now only the sidebar color works for me but the background does not work, You can look at the picture (sorry if I'm so long and boring to explain :) I just want you to understand the problem as clearly as possible)
I decided to check if I get a picture and yes I get
Now that you understand the problem, I will be interested in hearing your advice, thank you for paying attention to my long question.
Before I demonstrate the solution, I would like to say that the problem lies with me, I, as always, introduced myself impatiently and inattentively: (it turns out that I forgot that in the SideBar component I get the SideBarBackground value in short, the code looked like this
const {someValue} = useContext(SideBarContext);
const {SideBarValue, SideBarWallpaperValue} = React.useContext(CounterContext);
const [SideBarTheme] = SideBarValue;
const [SideBarBackground] = SideBarWallpaperValue;
<div style={{backgroundImage: `url(${SideBarBackground})`}}>
...
</div>
Then I got the SideBarWallpaper value
<div style={{backgroundImage: `url(${SideBarBackground.SideBarWallpaper})`}}>
...
</div>
I have tried finding the answer to this on StackOverflow and there are some related posts (e.g. React Child Component Not Updating After Parent State Change) but I want to understand why this is not working...
I have a React application that will display a layout of character cards (that is, each card displays a different character). It uses a child component, CharacterBoard, that lays out the CharacterCards, which would be a grandchild component. I pass the characters down from the App to the CharacterBoard as props, and CharacterBoard in turn maps these out the CharacterCards.
The problem is that I want the state of the character to change when I click on one of them. Specifically, I want the revealed field to change. However, even though the state change is reflected in the array of characters in the App (that is, the revealed field changes correctly), and the change is reflected in the array of characters in CharacterBoard, but not in CharacterCard. In fact, my mapping does not seem to be called at all in CharacterBoard when the props change.
Do I need to use something like getDerivedStateFromProps in CharacterBoard and set the state of that component and then use the state to map the values down to CharacterCard? If so, why?
In short (tl;dr), can you pass props on down through the component chain and map them out along the way and still have all changes reflected automatically?
Thanks for any guidance.
If it helps, the render method of my App is
render() {
const {state: {characters}} = this
return (
<div>
<header>
</header>
<main>
<CharacterBoard
onCardSelected={this.onCardSelected}
rowSize={logic.ROW_SIZE}
characters={characters}
cardSize={this.CARD_SIZE}/>
</main>
</div>
);
}
that of CharacterBoard is
render() {
const {props: {characters, rowSize, cardSize,onCardSelected}} = this
const rowUnit = 12 / rowSize
const cardLayout = characters
.map((character, i) => (
<Col xs={6} sm={rowUnit} key={character.name}>
<CharacterCard
onCardSelected = {onCardSelected}
key={i + Math.random()}
character={character}
cardSize={cardSize}
/>
</Col>
)
)
return (
<div>
<Container>
<Row>
{cardLayout}
</Row>
</Container>
</div>
)
}
and finally CharacterCard has this render method
render() {
const {props: {character, cardSize}} = this
const {thumbnail, revealed} = character
const imgURL = `${thumbnail.path}/${cardSize}.${thumbnail.extension}`
const topCardClass = classNames('characterCard__card-back', {'characterCard__card-back--hidden': revealed})
console.log(revealed)
return < a href="/#" onClick={this.onCardSelected}>
<div className='characterCard__card'>
<div className={topCardClass}>
<img src="/images/card_back.png" alt=""/>
</div>
< div className='characterCard__card-front'>< img alt=''
src={imgURL}/>
</div>
</div>
</a>
}
Doh! A simple forgetting to setState in App. Knowing that it should work made me go back through the code one more time and see that, indeed, it was a stupid error on my part.
i'm trying to do a CardList items from a local data.json file using React.Js.
To load the data i'm using a map function:
const ItemsList = data.map(item=>{
return(
<li><img key={item.id} src={"assets/images/sampleImages/" + item.image}/></li>
)
})
Code - PasteBin
but i cannot get the image. No error, just a broken image icon appear.
I've try:
This solution And with URL works, but don't work with path.
Also this thread. And nothing works.
Firstly import the image like this (You can amend it accordingly)
import imageBaseURL = "./assets/images/sampleImages/";
Then inside your ItemList make use of Template Literals like this :
const ItemsList = data.map( item => {
return(
<li><img key={item.id} alt="TitleOfImage" src={`${imageBaseURL}${item.image}`}/></li>
)
})
First step:
Importing image and store it in one variable ( ExampleImg )
import ExampleImg from '../example.png';
Second step:
Inject the image as a src
<img src = { ExampleImg } />
I am trying to create a email in React using the MJML email library. It runs off react and I have it all working but I need to render 2 sections rather than 1. When I render 1 it doesn't appear properly on the webpage as I need them to be different sizes.
When I try and wrap the elements within a array the return become null, take out one of the sections and it gets returned.
Any help would be appreciated, here is the code.
render() {
const { mjAttribute } = this.props
const content = [this.renderEmailOverhead()]
const innerContent = [this.renderEmailBanner(), this.renderEmailTitle(), this.renderEmailText(), this.renderEmailDivider]
return ([
<Section full-width='full-width' padding-top="0">
{ content }
</Section>,
<Section>
{ innerContent }
</Section>
])
}
Well, render method of a component can only return one element. so you'll have to wrap it in a divas Zargold mentioned.
Note that MJML component are more than a standard React component.
It has some internal logic not available in a React context. IMO you should generate MJML as standard HTML element and render it with a renderToStaticMarkup then pass it to mjml2html function as a string and mjml will compiles
return (
<mjml>
<mj-body>
<mj-container>
... // your sections goes here
</mj-container>
</mj-body>
</mjml>
)
Note that I don't think React is the best suited for this kind of work, I would recommend you to use a templating language such as mustache/handlebars which fit better.
You cannot use JSX interspersed with JavaScript like that... you could either do (you must have only one parent/root element).
<div>
<Section full-width='full-width' padding-top="0">
{ content }
</Section>
<Section>
{ innerContent }
</Section>
</div>
Or You could if you insist on using an array for some reason:
renderSection(content, fullWidth){
return (
<Section
full-width={fullWidth ? 'full-width' : false}
style={{paddingTop: fullWidth ? 0 : 'auto'}}
>
{content}
</Section>
)
}
render(){
let contents = [content, innerContent]
return(
<div>
{contents.map(section, i => renderSection(section, i % 2 === 0))
</div>
)