Undefined when passing props to siblings reactJS - javascript

new to react and trying to passdown, props to components with react. but gets undefined result when receiving {this.props.name} in Track.js. And TypeError: Cannot read property 'name' of undefined
when trying with {this.props.track.name} in Track.js render method.
It should render these tracks:
tracks: [{
name: 'Gold Slug',
artist: 'DJ khaled',
album: 'We da best',
id: '102 sample ID'
},
{
name: 'Slim shady',
artist: 'Eminem',
album: 'Marshal materials',
id: '103 sample ID'
}
Or this track:
searchResults: [{
name: 'You Mine',
artist: 'DJ Khaled',
album: 'I Changed a Lot',
id: '101 sample ID'
}],
Background info: Building an app that renders song tracks with name, artist and album. Also a search with search results and a playlist. I'm working with 6 components: App, PlayList, SearchBar, SearchResults, Track and TrackList.
App is a container. PlayList lets users adds Tracks to it. SearchResults displays results from SearchBar.
In App.js, I've set the state of searchResults in the constructor method and passed it down to component.
App.js:
import React from 'react';
import './App.css';
import SearchBar from '../SearchBar/SearchBar'
import SearchResults from "../SearchResults/SearchResults";
import Playlist from "../Playlist/Playlist";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
searchResults: [{
name: 'You Mine',
artist: 'DJ Khaled',
album: 'I Changed a Lot',
id: '101 sample ID'
}],
tracks: [{
name: 'Gold Slug',
artist: 'DJ khaled',
album: 'We da best',
id: '102 sample ID'
},
{
name: 'Slim shady',
artist: 'Eminem',
album: 'Marshal materials',
id: '103 sample ID'
}
]
};
}
render() {
return (
<div>
<h1>Ja<span className="highlight">mmm</span>ing</h1>
<div className="App">
<SearchBar />
<div className="App-playlist">
<SearchResults searchResults={this.state.searchResults}/>
<Playlist />
</div>
</div>
</div>
);
}
}
export default App;
SearchResults receives and .map iterates through the array and sets it to tracks within the TrackList component within render method.
SearchResults.js:
import React from 'react';
import './SearchResults.css'
import TrackList from "../TrackList/TrackList";
import Track from "../Track/Track";
class SearchResults extends React.Component {
render() {
return (
//Adds a map method that renders a set of Track components on the tracks attribute.
<div className="SearchResults">
<h2>Results</h2>
<TrackList tracks={this.props.searchResults.map(track => {
return <Track key={track.id} /> }
)} />
</div>
)
}
}
export default SearchResults;
TrackList.js renders a set of track components:
import React from 'react';
import './TrackList.css'
import Track from '../Track/Track'
class TrackList extends React.Component {
render() {
return (
<div className="TrackList">
<Track />
<Track />
<Track />
<Track />
</div>
)
}
}
export default TrackList;
Track.js renders Tracks:
import React from 'react';
import './Track.css'
class Track extends React.Component {
renderAction() {
if (this.props.isRemoval == true) {
return <h1>-</h1>;
} else {
return <h1>+</h1>;
}
}
//TODO: Fix rendering method on this.props.track.name
render() {
return (
<div className="Track">
<div className="Track-information">
<h3>{this.props.name}</h3>
<p>{`${this.props.artist} | ${this.props.album}`}</p>
</div>
<a className="Track-action" isRemoval={true}></a>
</div>
)
}
}
export default Track;

The issue here is that you are not actually passing data down to the Track component.
class SearchResults extends React.Component {
render() {
return (
//Adds a map method that renders a set of Track components on the tracks attribute.
<div className="SearchResults">
<h2>Results</h2>
<TrackList tracks={this.props.searchResults.map(track => {
return <Track key={track.id} /> }
)} />
</div>
)
}
}
Seems like SearchResults is trying to map thru the data is got via props, and render a Track for each one. Now if you look at this line right here, you will notice that no data is actually passed.
return <Track key={track.id} /> }
I think to fix your issue, all you would need to do is this.
class SearchResults extends React.Component {
render() {
return (
//Adds a map method that renders a set of Track components on the tracks attribute.
<div className="SearchResults">
<h2>Results</h2>
<TrackList tracks={this.props.searchResults.map(track => {
return <Track key={track.id} track={track} /> }
)} />
</div>
)
}
}
Now in the Track component you can access this.props.track.whatever.

Related

React using States from different paths

I want to take movie title when I click add to favorite button in movieItem.js and want to add my state in Favorites.js
import React, { Component } from 'react';
import { store } from '../..';
import './MovieItem.css';
class MovieItem extends Component {
render() {
const { Title, Year, Poster } = this.props;
console.log(this.props.Poster);
return (
<article className="movie-item">
<img className="movie-item__poster" src={Poster} alt={Title} />
<div className="movie-item__info">
<h3 className="movie-item__title">{Title} ({Year})</h3>
<button onClick={()=>console.log(Title)} type="button" className="movie-item__add-button">Добавить в список</button>
</div>
</article>
);
}
}
export default MovieItem;
That is my favoriteMovie.js
import React, { Component } from 'react';
import './Favorites.css';
class Favorites extends Component {
state = {
title: '',
movies: [
{ imdbID: 'tt0068646', title: 'The Godfather', year: 1972 }
]
}
render() {
return (
<div className="favorites">
<input value="Новый список" className="favorites__name" />
<ul className="favorites__list">
{this.state.movies.map((item) => {
return <li key={item.id}>{item.title} ({item.year})</li>;
})}
</ul>
<button type="button" className="favorites__save">Сохранить список</button>
</div>
);
}
}
export default Favorites;
Simply I want to take Title from Movie.js and add it to state which placed in favoriteMovie.js
Try to use context or redux to store your list of favourites movies and save there some important info like ID title etc etc and then on map check if some id is included in your list of favourites and if it is add some start there

.map undefined on array of object

I am passing array of object as a prop from App.js -> searchResult -> TrackList.js. But when I apply .map function on the array of object it shows Cannot read property 'map' of undefined . I have tried different ways to solve this but none of them worked. In console I am getting the value of prop. And my TRackList.js component is rendering four times on a single run. Here is the code
App.js
this.state = {
searchResults: [
{
id: 1,
name: "ritik",
artist: "melilow"
},
{
id: 2,
name: "par",
artist: "ron"
},
{
id: 3,
name: "make",
artist: "zay z"
}
]
return ( <SearchResults searchResults={this.state.searchResults} /> )
In Searchresult .js
<TrackList tracked={this.props.searchResults} />
In TrackList.js
import React from "react";
import Track from "./Track";
export default class TrackList extends React.Component {
constructor(props) {
super();
}
render() {
console.log("here", this.props.tracked);
return (
<div>
<div className="TrackList">
{this.props.tracked.map(track => {
return (<Track track={track} key={track.id} />);
})}
</div>
</div>
);
}
}
Here is the full code -- https://codesandbox.io/s/jamming-ygs5n?file=/src/components/TrackList.js:0-431
You were loading the Component TrackList twice. One time with no property passed, that's why it was first set in console then looks like it's unset, but it's just a second log. I have updated your code. Take a look here https://codesandbox.io/s/jamming-ddc6l?file=/src/components/PlayList.js
You need to check this.props.tracked.map is exists before the loop.
Solution Sandbox link:https://codesandbox.io/s/jamming-spf7f?file=/src/components/TrackList.js
import React from "react";
import Track from "./Track";
import PropTypes from 'prop-types';
export default class TrackList extends React.Component {
constructor(props) {
super();
}
render() {
console.log("here", typeof this.props.tracked);
return (
<div>
<div className="TrackList">
{this.props.tracked && this.props.tracked.map(track => {
return <Track track={track} key={track.id} />;
})}
</div>
</div>
);
}
}
TrackList.propTypes = {
tracked: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
artist: PropTypes.string,
}))
};
You need to check this.props.tracked value before implementing the map function.
you can simply check using this.props.tracked && follow your code.
You should add searchResults={this.state.searchResults} in your app.js to Playlist, take it in Playlist with props, and then set it in TrackList from Playlist (tracked={props.searchResults}).
Also, Typescript helps me not to do such mistakes.
Also, add a key prop to your component that you return in the map function.

How to add links in React Array Object

I have a React component that maps data from a .js file, containing objects in array. How can I link my title and images from within this function to access respective pages.
The title of an array of objects is 'Practices' which should open a new practices page when clicked. Within this object, there are a number of items, each of which contain an image of a practice, which when clicked must go to that specific practice page.
Here is sample code from my Practice_Data File..
const PRACTICES_DATA = [
{
id: 1,
title: 'Practices',
routeName: 'practices',
items: [
{
id: 1,
name: 'Defending Centrally | Opposed Skill (12-P5)',
imageUrl: 'https://image.mux.com/D8PU0036BeX3veIIzAKJlqiECDBoEIJak/animated.gif?width=490&height=278&fps=15',
Theme: 12,
},
]
},
export default PRACTICES_DATA;
Here is the code for my practice component:
import React from 'react';
import PRACTICES_DATA from './practices.data';
import CollectionPreview from '../../components/collection-preview/collection-preview';
class PracticesPage extends React.Component {
constructor(props) {
super(props);
this.state = {
collections: PRACTICES_DATA
};
}
render() {
const {collections} = this.state;
return (
<div className='practices-page'>
{collections.map(({ id, ...otherCollectionProps }) => (
<CollectionPreview key={id} {...otherCollectionProps} />
))}
</div>
);
}
}
export default PracticesPage;
There might well be an obvious answer to this, but I have been stuck on this for a while. Any help would be greatly appreciated.
EDIT:
Yes using react router here. The Collection Preview Code is shown below:
import React from 'react';
import CollectionItem from '../collection-item/collection-item.component';
import './collection-preview.styles.scss';
const CollectionPreview =({ title, items }) => (
<div className='collection-preview'>
<h1 className='title'>{title.toUpperCase()}</h1>
<div className='preview'>
{items.filter((item, idx) => idx < 4)
.map(({ id, ...otherItemProps }) => (
<CollectionItem key={id} {...otherItemProps} />
))}
</div>
</div>
);
export default CollectionPreview;

Passing different values from an array to a component

I have an array with different values in state within my component.
I want to dynamically render different sections of an array to the same component but on different pages of my react app.
i.e Pass props down to Component that renders the first title of the array on one page but then render the second title on another page.
Can anyone help?
import React from 'react';
import ChartItem from './chart-item.component.js'
import Popup from './modal/index.js'
//styles
import './chart-slides.styles.css'
class Chart extends React.Component {
constructor() {
super();
this.state = {
sections: [
{
title: 'How do you compare to the competition?',
id: 'chart1',
iframeUrl: 'https://app.chattermill.io/c/f4a52535-b2b9-4d71-9ac7-e198c9452e3f?compact=true'
},
{
title: 'Main drivers of positive sentiment sentiment are brand, service, and app exeprience. While bugs and security features are big drivers of negative sentiment',
id: 'chart2',
iframeUrl: 'https://app.chattermill.io/c/f4a52535-b2b9-4d71-9ac7-e198c9452e3f?compact=true'
},
{
title: 'Scroll through the feedback to see the pain points for customers',
id: 'chart3',
iframeUrl: 'https://app.chattermill.io/c/f4a52535-b2b9-4d71-9ac7-e198c9452e3f?compact=true'
}
]
};
}
render() {
return (
<div>
{this.state.sections.map(({ id, title, iframeUrl }) => (
<ChartItem key={id} title={title} url={iframeUrl} />
))}
<Popup/>
</div>
);
}
}
export default Chart;
How can I only render the first section from my array in this component below? The component below will be showed in multiple pages within the app.
import React from 'react';
import Popup from '../modal/index.js'
import { Heading } from 'rebass'
import './chart-slides.styles.css'
import Iframe from 'react-iframe'
const ChartItem = ({ title, iframeUrl, id }) => (
<div>
<a className="demo-btn" id="demo-btn-chart1" href="https://app.hubspot.com/meetings/jack123/presentation" target="_blank" rel="noopener noreferrer"> Book Demo</a>
<Heading fontSize="2.8vh" textColor="secondary" className="mobile-chart-title" as='h1'>
{title}
</Heading>
<Iframe
url={iframeUrl}
className="iframe-container"
/>
</div>
);
export default ChartItem

Why is this an error when rendering a component?

I'm trying to render a state via props to a nested component. This is what I have in my App.js:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
searchResults: [
{name: 'Money Trees',
artist: 'Kendrick Lamar',
album: 'Album Title',
id: '1234'},
{name: 'Reptilia',
artist: 'The Stroks',
album: 'Is This It',
id: '234'}
]
};
}
render() {
return (
<div>
<h1>
Ja<span className="highlight">mmm</span>ing
</h1>
<div className="App">
<SearchBar />
<div className="App-playlist">
<SearchResults searchResults={this.state.searchResults} />
<Playlist />
</div>
</div>
</div>
);
}
}
export default App;
Inside Playlist.js I have this:
class Playlist extends React.Component {
render() {
return (
<div className="Playlist">
<input defaultValue={'New Playlist'} />
<Tracklist />
<a className="Playlist-save"></a>
</div>
);
}
}
export default Playlist;
Now, I'm able to pass in the tracks props through a SearchResults component and into a Tracklist component. However, I'm getting an error when trying to map the tracks prop:
TypeError: Cannot read property 'map' of undefined
When I remove the Playlist component from the App file, the error fixes itself. I'm not sure why I get the error when I toss in <Playlist /> inside the main App.js file. Can someone help me understand that?
This is what Tracklist.js looks like:
class Tracklist extends React.Component {
constructor(props){
super(props);
}
render() {
return (
<div className="TrackList">
{this.props.tracks.map(track => <Track track={track} key={track.id} />)}
</div>
);
}
}
export default Tracklist;
Playlist renders Tracklist and it expects tracks props.
Try:
class Playlist extends React.Component {
render() {
return (
<div className="Playlist">
<input defaultValue={'New Playlist'} />
<Tracklist tracks={[]} />
<a className="Playlist-save"></a>
</div>
);
}
}
To see if the error disappears.

Categories

Resources