Update:
Basically i want the same output but i restructured the content. I'm not sure if your answers are still up for that.
Please check my sandbox feel free to fork it here:
https://codesandbox.io/s/get-the-property-value-forked-hutww
So on ContentData.js i want my image alt tag to be dynamic and pull the content of it from key name it something like this alt={this.name} and it will generate to alt="My alt tags"
See the codes below:
Content.js
import React, { Component } from "react";
import mainListsItems from "./ContentData";
class Content extends Component {
render() {
const myContent = mainListsItems.map((lists, k) => (
<>
<div key={k}>{lists.text}</div>
{lists.mainContent.map((subcontent, j) => {
return <div key={j}>{subcontent.contentAll}</div>;
})}
</>
));
return <>{myContent}</>;
}
}
export default Content;
ContentData.js
import React from "react";
const listsData = [
{
id: 1,
name: "My alt tags",
text: (
<>
<p>Lorem Imsum</p>
</>
),
mainContent: [
{
contentAll: (
<>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry.
</p>
<img
alt=""
src="https://images.unsplash.com/photo-1637704758245-ed126909d374?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxNHx8fGVufDB8fHx8&auto=format&fit=crop&w=500&q=60"
/>
</>
)
}
]
}
];
export default listsData;
content is defined inside the object while the object is being defined. So there is no name yet when content is being defined. Only after the assignment does name exist. You're referencing something that doesn't exist yet. So instead you can create a function that will be called at a later point after the object is defined and then the name can be referenced as shown below.
export default function App() {
const myData = [
{
id: 1,
name: "Lorem Ipsum",
content: function(){
return (
<>
<img
src="https://images.unsplash.com/photo-1637704758245-ed126909d374?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxNHx8fGVufDB8fHx8&auto=format&fit=crop&w=500&q=60"
alt={this.name}
/>
</>
)
}
}
];
const output = myData.map((x) => (
<>
<div key={x.id}>
<p>{x.name} sa</p>
<p>{x.content()}</p>
</div>
</>
));
return <div className="App">{output}</div>;
}
The this, in your case is referring the window object.
You can try to pass the name as a function value.
Something like this :
const myData = [
{
id: 1,
name: "Lorem Ipsum",
content: (alt) => (
<>
<img
src="https://images.unsplash.com/photo-1637704758245-ed126909d374?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxNHx8fGVufDB8fHx8&auto=format&fit=crop&w=500&q=60"
alt={alt}
/>
</>
)
}
];
const output = myData.map((x) => (
<div key={x.id}>
<p>{x.name} sa</p>
<p>{x.content(x.name)}</p>
</div>
));
You can replace the object in your myData array with a self executing function like this:
const myData = [
function(){
const entry = {
id: 1,
name: "Lorem Ipsum",
}
return {
...entry,
content: (
<>
<img
src="your image source"
alt={entry.name}
/>
</>
)
}
}()
];
Related
I'm new to React but hopefully someone can help!
So I've just created a component that takes in a value (via prop) and then .maps over that value creating an Image slider. The props are all an array of objects that contain different values such as :
const Songs = [
{
artist: 'Artist Name',
song: 'Song Name',
lenght: '2:36',
poster: 'images/....jpg'
},
{
artist: 'Artist Name',
song: 'Song Name',
lenght: '2:36',
poster: 'images/....jpg'
},
]
I have been making the same component over and over again because I don't know how to make the 'prop'.map value dynamic. Essentially I don't know how to change the value before the .map each different prop.
Here's an example. I want to make 'Songs'.map dynamic so the new props can replace that so they can also be mapped. Maybe there's another way. Hopefully some can help.
import React from 'react';
import { FaCaretDown } from 'react-icons/fa';
function ImageSlider({Songs, KidsMovies, Movies, TvShows}) {
return (
<>
{Songs.map((image, index) => (
<div className="movie-card">
<img src={'https://image.tmdb.org/t/p/w500' + image.poster_path}
className='movie-img' />
<h5 className='movie-card-desc'>{image.original_title}</h5>
<p className='movie-card-overview'>{movie.overview}</p>
</div>
))}
</>
);
}
export default ImageSlider;
Given your example,
I feel like all you need is render ImageSlides for each array
function ImageSlider({ items }) {
return (
<>
{items.map((item, idx) => (
<div ... key={idx}> // be careful to not forget to put a key when you map components
...
</div>
))}
</>
);
}
When rendering your component
function OtherComponent({ songs, kidsMovies, movies, tvShows }) {
return (
<div>
<ImageSlider items={songs} />
<ImageSlider items={kidsMovies} />
<ImageSlider items={movies} />
<ImageSlider items={tvShows} />
</div>
);
}
I have App, that is the parent component and I have the Child component:
The Child component gets a props called items so it can be reused depending on the data. It the example there is data, data1 and data2.
The thing is that I want to set a cookie from the parent component, to set the cookie I need the property link from data2, but I am already mapping data2 in the Child component.
What can I do to obtain the value of the property link in the parent component to pass it as an arguement here:
<Child
onClick={() =>
handleUpdate('How can I obtain here the string from link of data2?')
}
items={data2}
/>
This is the whole example code:
import * as React from 'react';
import './style.css';
const data = [
{ title: 'hey', description: 'description' },
{ title: 'hey1', description: 'description' },
{ title: 'hey2', description: 'description' },
];
const data1 = [
{ title: 'hey', description: 'description' },
{ title: 'hey1', description: 'description' },
{ title: 'hey2', description: 'description' },
];
const data2 = [
{ title: 'hey', link: 'link/hey' },
{ title: 'hey1', link: 'link/he1' },
{ title: 'hey2', link: 'link/he2' },
];
export default function App() {
const [, setCookie] = useCookie('example');
const handleUpdate = (cookie) => {
setCookie(null);
setCookie(cookie);
};
return (
<div>
<h2>App - Parent</h2>
<Child items={data} />
<Child items={data1} />
<Child
onClick={() =>
handleUpdate('How can I obtain here the string from link of data2?')
}
items={data2}
/>
</div>
);
}
export function Child({ items }) {
return (
<div>
<h2>Child</h2>
<ul>
{items.map((item) => {
return (
<>
<p>{item.title}</p>
<a href={item.link}>Go to title</a>
</>
);
})}
</ul>
</div>
);
}
Thank you!
If you want to get the link from the Child component you can simply add a link parameter in the callback:
<Child
onClick={(link) => handleUpdate(link)}
items={data2}
/>
Then from the Child you just need to call the onClick prop:
export function Child({ items, onClick }) { // here make sure to add the prop while destructuring
<a href={item.link} onClick={() => onClick(item.link)}>Go to title</a>
The map method doesn't change the array that it is called on, it just returns a new array, do the items array doesn't get affected at all here, so you can just call it normally like so:
return (
<div>
<h2>App - Parent</h2>
<Child items={data} />
<Child items={data1} />
<Child
onClick={() =>
handleUpdate(data2[0].link)
}
items={data2}
/>
</div>
);
Also, your Child component needs to accept the onClick function as a prop like so:
export function Child({ items, handleClick }) {
return (
<div onClick={handleClick}>
<h2>Child</h2>
<ul>
{items.map((item) => {
return (
<>
<p>{item.title}</p>
<a href={item.link}>Go to title</a>
</>
);
})}
</ul>
</div>
);
}
i have this part of code the map function did not show any element of the array, if i console.log the variable it shows me the elements but for some reasons i can't show the elements on the screen.
Code
function Solution({list}){
const data = list
console.log(data);
return(
<div>
{
data?.map((item) => {
return (
<div>
<p> {item.title} </p>
</div>
)
})
}
</div>
)
}
export default Solution;
const list = [
{
title: "Home"
},
{
title: "Service",
subItem: ["Clean", "Cook"]
},
{
title: "Kitchen",
subItem: ["Wash", "Dish"]
},
];
Solution({list})
Please, just pass "list" link this.
<Solution list={list}/>
Hope will help you, Thanks)
Check this out
import React from 'react';
function Solution({list}){
const data = list
console.log(list);
return(
<div>
{
data?.map((item) => {
return (
<div key={item.id}>
<p> {item.title} </p>
</div>
)
})
}
</div>
)
}
export function App(props) {
const list = [
{
id:1,
title: "Home"
},
{
id:2,
title: "Service",
subItem: ["Clean", "Cook"]
},
{
id:3,
title: "Kitchen",
subItem: ["Wash", "Dish"]
},
];
return (
<div className='App'>
<Solution list={list} />
</div>
);
}
// Log to console
console.log('Hello console')
Have a unique key prop for each element when you map an array and send list array as props to your Solution component
I want to get JSX in an object (foundCategory) from another file categoriesDetails, by using the find funtion through checking the item.title. Below is my code
Here How I m retrieving and want to send data as props to a component (CategoryDetails).
import type { NextPage } from 'next';
import CategoryDetails from '../components/CategoryDetails.jsx'
import {categoryDetails} from '../utils/categoriesDetails'
const Home: NextPage = () => {
let foundCategory = null;
foundCategory = categoryDetails.find(function(item){
return item.title === 'Bus Plugs'
})
console.log(foundCategory)
return (
<>
<Header />
{foundCategory ? <CategoryDetails
oDetails={foundCategory.details}
sTitle={foundCategory.title}
/> : ''
}
<FooterBar/>
</>
)
}
export default Home
and Here is my categoriesDetails.js from which I m exporting categories data (Simplified)
export const categoryDetails = [
{
title: 'Bus Plugs',
details: (
<div>
<ul> </ul>
<img src={`${categoryImagesDir}bus-plugs-large.jpg`} />
</div>
)
},
{
title: 'Fuse',
details: (
<div>
<ul> </ul>
<img src={`${categoryImagesDir}fuse-large.jpg`} />
</div>
)
}
But when I console to check, I get the following result instead the actual JSX in foundCategory.details. which I want to use in child component (CategoryDetails).
{
title: 'Bus Plugs',
details: {
'$$typeof': Symbol(react.element),
type: 'div',
key: null,
ref: null,
props: { children: [Array] },
_owner: null,
_store: {}
}
}
Looking forward,
thanks
In your Home component, you have this code:
foundCategory = categoryDetails.find(function(item){
return item.title = 'Bus Plug'
})
item.title = "Bus Plug" doesn't check for equality, it sets item.title to "Bus Plug".
you have to change this line to this:
return item.title === 'Bus Plug'
Try rewriting item.details to a function:
details: () => (
<div>
<ul></ul>
<img src={`${categoryImagesDir}fuse-large.jpg`} />
</div>
)
I have some code in codesandbox that is made up of 4 divs, 2 with the category "Book" and 2 with the category "Article". Some buttons at the top should trigger if all the divs should be displayed, only the books, or only the articles. All the buttons show every div currently, so the page doesn't change and it looks like the state stays the same
Here is the code which is on the sandbox
App.js
import React, { useState } from "react";
/* import Container from './design/Container' */
import Test from "./Test";
const posts = [
{
title: "React Hooks",
content: "The greatest thing since sliced bread!",
category: "Book"
},
{
title: "Using React Fragments",
content: "Keeping the DOM tree clean!",
category: "Article"
},
{
title: "Angular Hooks",
content: "The greatest thing since sliced bread!",
category: "Book"
},
{
title: "Angular Fragments",
content: "Keeping the DOM tree clean!",
category: "Article"
}
];
export default function App() {
const [productItems, setProductItems] = useState(posts);
function handleButton(e) {
console.log(e.target.value);
if (e.target.value === "All") {
setProductItems(posts);
} else {
setProductItems(
posts.filter((p, i) => <div key={i}>p.category === e.target.value</div>)
);
}
setProductItems(posts);
console.log(productItems);
}
return (
<div>
<Test posts={productItems} handleButton={handleButton} />
</div>
);
}
Test.js
import React from "react";
function Post({ p,title, content, category }) {
return (
<React.Fragment>
<div>
<h3>{p.title}</h3>
<div>{p.content}</div>
<br />
<i>
in <b>{p.category}</b>
</i>
</div>
</React.Fragment>
);
}
export default function Test({handleButton, posts = [] }) {
return (
<React.Fragment>
<div>
<button value="All" onClick={handleButton}>
All
</button>
<button value="Book" onClick={handleButton}>
Book
</button>
<button value="Article" onClick={handleButton}>
Article
</button>
</div>
<div>
{posts.map((p) => {
return <Post key={p.title} p={p} />;
})}
</div>
</React.Fragment>
);
}
style.scss
.App {
font-family: sans-serif;
text-align: center;
}
You had a few things wrong, one was that you handleButton required an argument but you weren't passing one to it. You need to call it like onClick={(e) => handleButton(e)} another was that you set the state of product items again after your if statement. You had already set it to the filtered value, but then you overwrote it with the unfiltered value like setProductItems(posts); so you have to remove this line. Another was that your filter function didn't really make sense. I would look it up and learn more about it. It takes a function that returns a boolean; it doesn't return a div.
SOLUTION
(sandbox)
App.js
import React, { useState } from "react";
import Test from "./Test";
const posts = [
{
title: "React Hooks",
content: "The greatest thing since sliced bread!",
category: "Book"
},
{
title: "Using React Fragments",
content: "Keeping the DOM tree clean!",
category: "Article"
},
{
title: "Angular Hooks",
content: "The greatest thing since sliced bread!",
category: "Book"
},
{
title: "Angular Fragments",
content: "Keeping the DOM tree clean!",
category: "Article"
}
];
export default function App() {
const [productItems, setProductItems] = useState(posts);
function handleButton(e) {
console.log(e.target.value);
if (e.target.value === "All") {
setProductItems(posts);
} else {
setProductItems(posts.filter((p) => p.category === e.target.value));
}
console.log(productItems);
}
return (
<div>
<Test posts={productItems} handleButton={handleButton} />
</div>
);
}
Test.js
import React from "react";
const Post = ({ pa }) => {
return (
<React.Fragment>
<div>
<h3>{pa.title}</h3>
<div>{pa.content}</div>
<i>
in <b>{pa.category}</b>
</i>
</div>
</React.Fragment>
);
};
export default ({ posts = [], handleButton }) => (
<>
<div>
<button value="All" onClick={(e) => handleButton(e)}>
All
</button>
<button value="Book" onClick={(e) => handleButton(e)}>
Book
</button>
<button value="Article" onClick={(e) => handleButton(e)}>
Article
</button>
</div>
<div>
{posts.map((pa, i) => (
<Post key={i} pa={pa} />
))}
</div>
</>
);