Reputation: 161
I want to set that when I click onClick in the component Albums.js, I get the contents of the component photos.js. Specifically, choosing one album will trigger a photo array from this album using the Photos.js component.
Albums.js
import React from 'react';
import PropTypes from 'prop-types';
import './forAlbum.css'
class Albums extends React.Component {
constructor(props) {
super(props);
this.state = {
};
this.onClicks = this.onClicks.bind(this);
}
onClicks = () => {
console.log("lamus");
}
render () {
const albums = this.props.albums.map((album, i) => {
return (
<AlbumThumb name={album.name} img={album.photos[0].src} id={i} key={i} />
);
});
// console.log(albums);
console.log(this.onClicks);
return (
<div className="thumbContainer">{albums}</div>
)
}
}
const AlbumThumb = (props) => (
<div className="thumb">
<div className="thumbImgWrap">
<img src={require('./GalleryImages/' + props.img)} alt={props.name} />
</div>
<h3 className="thumbTitle">{props.name}</h3>
</div>
);
export default Albums;
This is Photos.js
import React from 'react';
import './forAlbum.css'
const Photos = (props) => {
const cliced = () => {
console.log("cliced");
}
const photos = props.photos.map(({ photos }) =>
<div>
<ul key={photos.id}>
{photos.id}
</ul>
{photos.map((eachThing, i) => {
return (
<PhotoMain name={eachThing.cap} img={eachThing.src} id={i} key={i} />
);
})}
</div>
);
// console.log(photos);
return <div className="thumbContainer" onClick={props.clicked}>{photos}</div>;
};
const PhotoMain = (props) => (
<div className="thumb" >
<div className="thumbImgWrap">
<img src={require('./GalleryImages/' + props.img)} alt={props.name} />
</div>
<h3 className="thumbTitle">{props.name}</h3>
</div>
);
export default Photos;
But i don't how to connect this, Maybe someone has an idea or suggestion?
I try to invoke this in next component GalleryPhotos.js
<Albums albums={data3} onClick={this.onClicks} />
<Photos photos={data3} />
const data3 = [
{
id: '1',
name: "Siatkówka",
photos: [
{
id: "11",
src: "siatkowka1.jpg",
cap: "Siatkówka"
},
{
id: "12",
src: "siatkowka2.jpg",
cap: "Siatkówka2"
},
{
id: "13",
src: "siatkowka3.jpg",
cap: "Siatkówka3"
}
]
},
{
id: '2',
name: "Piłka nożna",
photos:[
{
id: "21",
src: "pilkaNozna1.jpg",
cap: "Piłka nożna1"
},
{
id: "22",
src: "pilkaNozna2.jpeg",
cap: "Piłka nożna2"
},
{
id: "23",
src: "pilkaNozna3.jpg",
cap: "Piłka nożna3"
}
]
}
];
EDIT 1 - filter method
const Photos = (props) => {
const photos = props.photos.filter(photos => photos.id === '1').map(({photos}) =>
<div>
<ul key={photos.id}>
{photos.id}
</ul>
{photos.filter(eachThing => eachThing.id === eachThing.id).map((eachThing, i) =>
{
return (
<PhotoMain name={eachThing.cap} img={eachThing.src} id={i} key={i} />
);
})}
</div>
);
console.log(photos);
return <div className="thumbContainer">{photos}</div>;
};
I used the Filter.js method and thanks to it I am able to select by identifying the specific album ID, which photos must appear, but I am wondering how to set it as dynamic relative to the component. The biggest difficulty is understanding how the connections between components are made to make this filter effective. In addition, I wonder if the component Albums.js while filtering has something to logic
Edit 2: Console message:
Uncaught TypeError: props.photos.filter is not a function
at Photos (Photos.js:6)
at mountIndeterminateComponent (react-dom.development.js:14592)
at beginWork (react-dom.development.js:15082)
at performUnitOfWork (react-dom.development.js:17903)
at workLoop (react-dom.development.js:17944)
at HTMLUnknownElement.callCallback (react-dom.development.js:147)
at Object.invokeGuardedCallbackDev (react-dom.development.js:196)
at invokeGuardedCallback (react-dom.development.js:250)
at replayUnitOfWork (react-dom.development.js:17224)
at renderRoot (react-dom.development.js:18037)
at performWorkOnRoot (react-dom.development.js:18919)
at performWork (react-dom.development.js:18826)
at performSyncWork (react-dom.development.js:18799)
at interactiveUpdates$1 (react-dom.development.js:19109)
at interactiveUpdates (react-dom.development.js:2328)
at dispatchInteractiveEvent (react-dom.development.js:5134)
The above error occurred in the <Photos> component:
in Photos (at GalleryPhotosVideos.js:208)
in div (at GalleryPhotosVideos.js:204)
in div (at GalleryPhotosVideos.js:196)
in CSSTransitionGroupChild (created by TransitionGroup)
in span (created by TransitionGroup)
in TransitionGroup (created by CSSTransitionGroup)
in CSSTransitionGroup (at GalleryPhotosVideos.js:190)
in GalleryPhotosVideos (created by Route)
in Route (at Content.js:33)
in Switch (at Content.js:24)
in div (at Content.js:23)
in Content (at App.js:14)
in div (at App.js:12)
in App (at src/index.js:10)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:10)
Uncaught TypeError: props.photos.filter is not a function
at Photos (Photos.js:6)
at mountIndeterminateComponent (react-dom.development.js:14592)
at beginWork (react-dom.development.js:15082)
at performUnitOfWork (react-dom.development.js:17903)
at workLoop (react-dom.development.js:17944)
at renderRoot (react-dom.development.js:18022)
at performWorkOnRoot (react-dom.development.js:18919)
at performWork (react-dom.development.js:18826)
at performSyncWork (react-dom.development.js:18799)
at interactiveUpdates$1 (react-dom.development.js:19109)
at interactiveUpdates (react-dom.development.js:2328)
at dispatchInteractiveEvent (react-dom.development.js:5134)
This message I see when I click
TypeError: props.photos.filter is not a function
const photos = props.photos.filter(photos => photos.id === photos.id).map(({photos}) =>
Upvotes: 1
Views: 433
Reputation: 7492
The component containing your Album and Photos should only render the Photos component if a state boolean value is true. When click on your album, this value will be updated :
import React, { Component } from 'react'
class ThankYou extends Component {
constructor(props) {
super(props)
this.state = {
showPhotos: false
}
}
albumClicked = ev => {
this.setState({ showPhotos: true })
}
render() {
return (
<>
<Albums albums={data3} onClick={this.albumClicked} />
{this.state.showPhotos && <Photos photos={data3} />}
</>
)
}
}
And then call the function passed in the album :
const AlbumThumb = (props) => (
<div className="thumb" onClick={ev => {props.onClick()}}> //Calls the parent function when clicked
<div className="thumbImgWrap">
<img src={require('./GalleryImages/' + props.img)} alt={props.name} />
</div>
<h3 className="thumbTitle">{props.name}</h3>
</div>
);
EDIT :
I did not notice that AlbumThumb
wasn't your component. You will have to move the function up to the Album
render function (and remove it from AlbumThumb
) :
render() {
const albums = this.props.albums.map((album, i) => {
return (
<div onClick={ev => { props.onClick() }}>
<AlbumThumb name={album.name} img={album.photos[0].src} id={i} key={i} />
</div>
);
});
// console.log(albums);
console.log(this.onClicks);
return (
<div className="thumbContainer">{albums}</div>
)
}
EDIT 2 :
Filtering albums by owners name :
this.props.albums.filter(album => album.name.includes(myFilterString)).map(...
EDIT 3 :
Your parent class will have to be aware of wich album got selected, you will have to send your album data back to it using the onClick function :
const albums = this.props.albums.map((album, i) => {
return (
<div onClick={props.onClick(album)}>
<AlbumThumb name={album.name} img={album.photos[0].src} id={i} key={i} />
</div>
);
});
You can then tweak your parent class to store the whole selected album, and display photos depending on it :
class ThankYou extends Component {
constructor(props) {
super(props)
this.state = {
selectedAlbum: null
}
}
albumClicked = selectedAlbum => ev => {
this.setState({ selectedAlbum })
}
render() {
const { selectedAlbum } = this.state
return (
<>
<Albums albums={data3} onClick={this.albumClicked} />
{selectedAlbum && <Photos photos={data3.find(album => album.name === selectedAlbum.name)} />}
</>
)
}
}
Upvotes: 3
Reputation: 6598
Manage your data as state in an outer component as state. And pass it as props to both Album
and Photos
. Update photos from album component.
class Outer extends Component {
constructor(props) {
super(props)
this.state = {
photos: [],
albums: [
{
id: '1',
name: "Siatkówka",
photos: [
{
id: "11",
src: "siatkowka1.jpg",
cap: "Siatkówka"
},
{
id: "12",
src: "siatkowka2.jpg",
cap: "Siatkówka2"
},
{
id: "13",
src: "siatkowka3.jpg",
cap: "Siatkówka3"
}
]
},
{
id: '2',
name: "Piłka nożna",
photos:[
{
id: "21",
src: "pilkaNozna1.jpg",
cap: "Piłka nożna1"
},
{
id: "22",
src: "pilkaNozna2.jpeg",
cap: "Piłka nożna2"
},
{
id: "23",
src: "pilkaNozna3.jpg",
cap: "Piłka nożna3"
}
]
}
]
}
}
const updatePhotos = (albumId) => {
// pass this function to album as prop and bind with each album.
const album = this.state.albums.filter((album) => album.id === albumId)
this.setState({
photos: album.photos
})
}
render() {
<>
<Albums albums={this.state.albums} clickHandler={this.updatePhotos} />
{this.state.photos ? <Photos photos={this.state.photos} /> : null}
</>
}
}
In Albums
, call clickHandler with album id
<AlbumThumb name={album.name}
img={album.photos[0].src}
id={i}
key={i}
onClick={() => this.props.clickHandler(album.id)} />
Upvotes: 0