React create an thumbnail for each object dynamically - arrays

Hello guys im trying to create an div for each thumbnail in my personas ={[]} it should use this.props.personas.map something like this
{this.props.personas.map(thumbnail => {
return <div><img src={this.props.thumbnail /}></div>
})}
i already tried this but failed here is my bin. Bin
any suggestions? what im doing wrong

I am assuming the src for the images is in the personas array (i know you call it thumbnail, but for consistency sake let's use persona instead)? If so, you should use persona instead of this.props.thumbnail
{
this.props.personas.map((persona, i) => {
return <div key={i}><img src={persona.thumbnail} /></div>
})
}
The answer aside, it is good practice to use key prop on dynamically generated components. Read about keys here: https://facebook.github.io/react/docs/lists-and-keys.html#keys

Related

Next js | React - How to insert Google Ads in a page with dynamic content

I'm fetching articles from an API, and then I parse the HTML code:
function Article({ article }) {
return (
<PageContainer>
<div className={styles.container}>
{parser(article.content.html)}
</div>
</PageContainer>
)
;
}
My question is whats the best approach to insert a GoogleAdComponent when I get something like <div class='google_ad'></div> from the API?
I've tried adding a useEffect, check if there's a class with that name, then appendChild, but in React we need to create an element as a React Node and then add it to React.render() right?
I'm getting a feeling that there's an easier implementation, but I can't find any information online about this.
Thanks in advance :)
dangerouslySetInnerHTML is React’s replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it’s dangerous. For example:
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
https://reactjs.org/docs/dom-elements.html
But never use it with user input, only with trusted origins

I want to map over an array using React which in turn contains an object

I have an array which is structured as follows. I got this array from a postgresql db as:
[{"pp_all":"{"pp_ident":43,"pp_titel":"abc","pp_beschreibung":null}]
I use REACT to map over this array.
{gesamt.map((elemt, index) => (
<>
<h5 key={index}>{elemt.pp_all}</h5>
</>
))}
As a result I get the following to see in my browser:
{"pp_ident":43,"pp_titel":"abc","pp_beschreibung":null}
How do I get the value of the individual attributes?
EDIT
If i hover over the result data.pp_all i got the follwowing :
"{"pp_ident":43,"pp_titel":"abc","pp_beschreibung":null}"
So i think it is the wrong format in the frontend.
But how can it be, because if i print it out, i can see the above
And if i trie to do the following:
{gesamt.map((data) => {
console.log(data.pp_all.pp_titel);
})}
I got an undefined error
You need to target individual attribute with another dot. Like the following
{elemt.pp_all.pp_indent}
{elemt.pp.all.pp_titel} and so on..
Because you got the object so it works same like you would target and object's property
The answers absove will show you how to access the individual fields, but if you want to display all values the way you presented your html, you could loop over the keys of that object and return the value like this:
{gesamt.map((elemt, index) => (
<>
<h5 key={index}>{Object.keys(elemt.pp_all).map(key => elemt.pp_all[key])}</h5>
</>
))}
you need to iterate over each object to get attribute value
gesamt.map(data => {
for (let key in data ) {
<h5>{data[key].pp_titel}</h5>
<h4>{data[key].pp_ident}</h4>
}
})

Dynamic content inside Trans Component i18next

I have a list of translated keys and react component content.
e.g :
list = [{ translation: "Hello <1>World</1>", content: "Hello <a href='#'>World</a>" },
{ translation: "A <1>B</1>", content: "A <a href='#'>B</a>" }]
The idea is to show a translated data from the list using the "translation" and the structure of "content" with Trans Component of i18next-react with a map function.
{list.map((item) => (
<Trans i18nKey={item.translation}>
{item.content}
</Trans>))}
Unfortunately, this doesn't seem to work at all, the outcome is only the translated string, without the structure that should came by the React Component content.
Any idea how to work around this?
Your content is a pure string and not a react element. Therefore your code can't work -> it can't extract the a element from the string and replace the <1> with it.
edit below
sample:
{list.map((item) => (
<Trans
i18nKey={item.translation}
defaults={item.translation} // Hello <0>World</>
components={[World]}
</Trans>))}
You need to pass in the components to get interpolated into the "pseudo" tags <0>...details also have a look at https://react.i18next.com/misc/using-with-icu-format (for props defaults, components, values)
Just in case anyone will try to do this in the future:
The way to do so is to use components props as Jamuhl mentioned.
And to pass there an array with the HTML elements of the "item.content".
The way to get the array of HTML elements from a string as we have on "item.content" is by using ReactHtmlParser that parse that string into an HTML elements array!
ReactHtmlParser can be cloned from here: https://www.npmjs.com/package/react-html-parser
For who still have problem.
make sure you have correct order of nested html
like
key ="<0><0/><1>translated here</1></0>";
function createMarkup()
{
return <div><input type="checkbox" /><label>translate here</label></div>;
}
<Trans i18nKey="key" >{ReactHtmlParser(createMarkup())}</Trans>

Setting span labels with a loop

I pulled data with request and now I'm trying to present each result on my site. I get an array with genres each time, so I need some ideas on how I could use loops in JSX in order to put those spans in result div that already has images, heading and stuff.
setGenres = () => {
let data = this.props.data.genres;
let labelsText = '';
for (let i = 0; i < data.length; i++) {
labelsText += <span className='genre'>data[i]</span>
}
return (labelsText);
}
<div className='result-info'>
<h4>{this.props.data.name}</h4>
{this.setGenres()}
</div>
Back when I was using vanilla JS, I could use string and put it via innerHTML, but now I have no idea what to do. It just returns [Object object] on my site.
You can use map to iterate over the array and return another result. So it's possible to return a portion of JSX which will be rendered inside your div:
<div className='result-info'>
<h4>{this.props.data.name}</h4>
{this.props.data.genres.map((genre,idx)=>(
<span key={idx} className='genre'>{genre}</span>
)}
</div>
JSX generates element classes for React to use. React allows rendering of various things, including arrays of React classes. In your scenario setGenres needs to change to the following.
setGenres = () => {
const data = this.props.data.genres;
const spans = data.map(genre => (<span key={genre} className='genre'>{genre}</span>));
return spans;
}
As noted by another user, I added the key prop as react will complain otherwise. It's best to set the key to something guaranteed to be unique, rather than just an index.
You can read more about array mapping here - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
You can read more about lists in react here - https://reactjs.org/docs/lists-and-keys.html

creating a list with react-dropzone

I'm trying to create a gallery using react-dropzone. I am successfully adding images but instead of creating an array, as I thought I was doing by following their github, it is simply loading an image and replacing it with the new one when I drag another image. The expected result is to add the image next to the one I already dragged in it.
I am specifying an empty array called files: [], that I imagine will collect the images.
The dropzone element in my class looks like this:
let dropzoneRef;
<Dropzone
ref={
(node) => {
dropzoneRef = node;
}
}
onDrop={this.onDrop.bind(this)}>
<p>Drop files here.</p>
</Dropzone>
<RaisedButton
label="Upload File"
primary={false}
className="primary-button"
onClick={() => { dropzoneRef.open(); }}
/>
<ul>
{
this.state.files.map(f =>
<li key={f.preview}>
<img className="dropped-image" src={f.preview} alt=""/>
</li>,
)
}
</ul>
I added the working code to a WebpackBin for you to inspect
Their github docs are here
This is my goal screen. I haven't worked out the second part which is clicking on any single thumbnail added and showing it in full size. So don't worry about that part. I just need to be able to collect a list and add as many as I want. Here is a screenshot of the expected result. (I apologize for the kindergarten writing)
Thank you in advance
All you need to do is update your onDrop function as follows
onDrop(uploadedFile) {
this.setState({
files: this.state.files.concat(uploadedFile),
});
}
This is because you want to add the new file to this.state.files array.
See this updated WebpackBin.

Resources