React Pass const from file to another - javascript

I have two page with same logic but different content and i want to use the same object but parse different json content.
Projects and Experience page use the same ProjectList and Project. I want to pass different content to Projects.js and Experience.js
Project:
import React, {Component} from 'react';
import Navigation from "../components/Nagivation";
import ProjectList from "../components/experience/ProjectList";
import { portfolioData } from '../data/portfolioData';
export default class Projects extends Component {
state = {
projects:portfolioData
};
render() {
let {projects} = this.state;
return (
<div className="portfolio">
<Navigation/>
{
<ProjectList
item={projects}
/>
}
</div>
);
}
};
ProjectList
import React, {Component} from 'react';
import Project from "./Project";
export default class ProjectList extends Component {
render() {
console.log(this.props.item)
let {projects} = this.props.item;
return (
<div className="portfolioContent">
<h3 className="radioDisplay">Test</h3>
<div className="projects">
{
projects.map(item => {
return (
<Project
key={item.id}
item={item}
/>
)
})
}
</div>
</div>
);
}
}
I have Uncaught TypeError: Cannot read properties of undefined (reading 'map') on the line <div className="projects">
Project.js
import React, {Component} from 'react';
export default class Project extends Component {
state = {
showInfo: false
}
handleInfo = () => {
this.setState({
showInfo:!this.state.showInfo
})
}
render() {
let {name, periode, info, picture} = this.props.item
return (
<div className="project">
<h5>{periode}</h5>
<h3>{name}</h3>
<img src={picture} alt="" onClick={this.handleInfo} />
//some stuffs
);
}
}
I don't want to use map, because i want to iterate only in ProjectList.

Related

React's map function problem with the sample

I am trying to view data using below sample. my list.js file as below:
import React, { Component } from 'react';
import { Person} from './Person';
export class List extends Component {
render() {
const persons = [
{
name:'Frank',
age:30,
city:'city 01'
},
{
name:'Hameed',
age:25,
city:'city 02'
},
{
name:'Jack',
age:24,
city:'city 03'
}
]
const personList = persons.map(person => <Person person={person}/>)
return <div> {personList} </div>
}
}
My person.js file is as below:
import React, { Component } from 'react';
export function Person (person){
return (
<div>
{person.name}
</div>
);
}
I need to print my array value inside the HTML but still did not render the view. I could not fix this.
My App.js file as below:
import logo from './logo.svg';
import './App.css';
import { List} from './components/List'
function App() {
return (
<div className="App">
<List></List>
</div>
);
}
export default App;
You pass the prop person to each <Person />, but inside the <Person /> component you are not getting it well. Each prop you pass, is getting to the function under the props variable, Try this code:
import React, { Component } from 'react';
export function Person (props){
return (
<div>
{props.person.name}
</div>
);
}
Or, alternatively, using destructuring:
import React, { Component } from 'react';
export function Person ({ person }){
return (
<div>
{person.name}
</div>
);
}
In <Person /> component you wrongly used props, try instead as:
export function Person (props) {
const { person } = props
// ... rest
}
See the difference from Person (person) to Person ({ person }). In the explained solution the person is destructured from props.
person.js
import React, { Component } from 'react';
export const Person = (props) => {
return (
<div>
{props.person.name}
</div>
);
}
or,
import React, { Component } from 'react';
export function Person (props){
return (
<div>
{props.person.name}
</div>
);
}

TypeError: props.tracks.map is not a function

I'm currently working on a react app exercise based around creating Spotify playlists. Here is the primary code-base:
App.js
import React from 'react';
import './App.css';
import SearchBar from'../SearchBar/SearchBar';
import SearchResults from '../SearchResults/SearchResults';
import Playlist from '../Playlist/Playlist';
const track = {
name: "Hello",
artist: "Again",
album: "Friend of a friend",
id: 0
};
const tracks = [track, track, track];
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
searchResults: tracks,
playlistName: "DEFAULT",
playlistTracks: tracks
};
this.addTrack = this.addTrack.bind(this);
this.removeTrack = this.removeTrack.bind(this);
}
addTrack(track) {
this.state.playlistTracks.map(id => {
if(track.id === id)
return;
});
this.setState((state, track) => ({
playlistTracks: state.playlistTracks.push(track)
}));
}
removeTrack(track) {
this.state.playlistTracks.map(id => {
if(track.id === id)
{
this.setState((state, track) => ({
playlistTracks: state.playlistTracks.remove(track)
}));
}
});
}
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} onAdd= {this.addTrack}/>
<Playlist name= {this.state.playlistName} tracks= {this.state.playlistTracks} onRemove= {this.removeTrack}/>
</div>
</div>
</div>
);
}
}
export default App;
Playlist.js
import React from 'react';
import './Playlist.css';
import TrackList from '../TrackList/TrackList';
function Playlist(props) {
return (
<div className="Playlist">
<input value="New Playlist"/>
<button className="Playlist-save">SAVE TO SPOTIFY</button>
<TrackList tracks= {props.tracks} onRemove= {props.onRemove} isRemoval= {true}/>
</div>
);
}
export default Playlist;
import React from 'react';
import './SearchBar.css';
function SearchBar () {
return (
<div className="SearchBar">
<input placeholder="Enter A Song, Album, or Artist" />
<button className="SearchButton">SEARCH</button>
</div>
);
}
export default SearchBar;
SearchBar.js
import React from 'react';
import './SearchBar.css';
function SearchBar () {
return (
<div className="SearchBar">
<input placeholder="Enter A Song, Album, or Artist" />
<button className="SearchButton">SEARCH</button>
</div>
);
}
export default SearchBar;
SearchResults.js
import React from 'react';
import './SearchResults.css';
import TrackList from '../TrackList/TrackList';
function SearchResults (props) {
return (
<div className="SearchResults">
<h2>Results</h2>
<TrackList tracks={props.searchResults} onAdd= {props.onAdd} isRemoval= {false}/>
</div>
);
}
export default SearchResults;
Track.js
import React from 'react';
import './Track.css';
class Track extends React.Component {
constructor(props) {
super(props);
this.addTrack = this.addTrack.bind(this);
this.removeTrack = this.addTrack.bind(this);
}
addTrack() {
this.props.onAdd(this.props.track);
}
removeTrack() {
this.props.onRemove(this.props.track);
}
render() {
return (
<div className="Track">
<div className="Track-information">
<h3>{ this.props.track.name }</h3>
<p>{ this.props.track.artist } | { this.props.track.album }</p>
<div onClick= {this.addTrack}>+</div>
<div onClick= {this.removeTrack}>-</div>
</div>
</div>
);
}
}
export default Track;
TrackList.js
import React from 'react';
import './TrackList.css';
import Track from '../Track/Track';
function TracklList (props) {
return (
<div className="TrackList">
{
props.tracks.map(track => {
return <Track
track={track}
key={track.id}
onAdd= {props.onAdd}
onRemoval= {props.onRemoval}
isRemove= {props.isRemove}
/>;
})
}
</div>
);
}
export default TracklList;
It's a very baseline application at the moment but I'm trying to test a certain functionality so far. I am trying to test the process of adding a song from the Results section into the Playlist. However, when I click the plus icon on one of the songs, I get the following bug:
The bug only pops up after I click the plus icon so my initial assumptions is that I am changing the state object from an array to a list. however, I don't kow how that is the case. Anyway, I could definitely use a second opinion so far!
Array.push mutate the calling array and returns a number indicate the length of the new array.
In your addTrack method, your old playlistTracks state was mutated and new state was set to be a number instead of the new array.
Use the spread syntax to add new item to your array in an immutable way.
Also setState accept a new state, or a function that received old state and return new state, track should be received from the addTrack method
P/S: the .map above the setState seems like it won't work as intended.
addTrack(track) {
/*
* NOTE: the code below doesn't affect anything since `map`
* will be applied on each item and does not stop when you `return`
* also, it seems like `playlistTracks` is an array of object, but was
* used as an array of string here
*/
this.state.playlistTracks.map(id => {
if (track.id === id)
return;
});
this.setState((state/* ,track -- I think this should be removed */) => ({
// old code: playlistTracks: state.playlistTracks.push(track)
playlistTracks: [...state.playlistTracks, track]
}));
}

I'm getting an undefined error in my project made with React

I am sending as a prop an array of objects. When I console.log(this.props) I get the array of objects, but when I try to assign it to a variable it gives me
TypeError:ninjas is undefined
This is how i send the prop
import React from 'react';
import Ninjas from './Ninjas';
class App extends React.Component {
state = {
ninjas:[
{name:"Ryu",age:"20",belt:"black",key:"1"},
{name:"Yoshi",age:"22",belt:"yellow",key:"2"},
{name:"Mario",age:"25",belt:"white",key:"1"}
]
}
render(){
return (
<div>
<h1>My first React App</h1>
<Ninjas list={ this.state.ninjas }/>
</div>
)
}
}
export default App;
And this is how i recibe it
import React from 'react';
class Ninjas extends React.Component {
render(){
const { ninjas } = this.props;
const ninjasList = ninjas.map(ninja => {
return(
<div className="ninja" key={ ninja.key }>
<div>Name: { ninja.name }</div>
<div>Age: { ninja.age }</div>
<div>Belt: { ninja.belt }</div>
</div>
)
})
return (
<div className="ninja-list">
{ ninjasList }
</div>
);
}
}
export default Ninjas;
<Ninjas list={ this.state.ninjas }/>
I suggest you change this to
<Ninjas ninjas={ this.state.ninjas }/>
Otherwise the name would be list in your child component.
In other words the name of the property you use when rendering the component (here in the render function of App) has to correspond to the name you get from the props object in your child component (here your child component is Ninjas).
You are passing ninjas in your Ninjas component <Ninjas list={ this.state.ninjas }/> using list props. So, you should be using this const { list } = this.props; instead of const { ninjas } = this.props; in your Ninjas Component.
import React from 'react';
class Ninjas extends React.Component {
render(){
const { list } = this.props;
const ninjasList = list.map(ninja => {
return(
<div className="ninja" key={ ninja.key }>
<div>Name: { ninja.name }</div>
<div>Age: { ninja.age }</div>
<div>Belt: { ninja.belt }</div>
</div>
)
})
return (
<div className="ninja-list">
{ ninjasList }
</div>
);
}
}
export default Ninjas;

onClick inside mapped object JSX for React NextJS not working

I have a component :
import React, { Component } from 'react';
import ImageItem from '../components/ImageItem';
class ImageList extends Component {
handleClick() {
console.log('Testing testing...'); // ---> This is not working.
}
render() {
const images = this.props.images.map(image => {
return (
<ImageItem
onClick={this.handleClick}
key={image.id}
image={image.src}
title={image.title}
/>
);
});
return (
<div className="image-list" ref={el => (this.el = el)}>
{images}
</div>
);
}
}
export default ImageList;
However, my onClick is not console logging anything out when it is inside the mapped function.
This is my ImageItem component:
import React, { Component } from 'react';
class ImageItem extends Component {
render() {
return (
<a href="#">
<img
className="portfolio-image"
src={this.props.image}
alt={this.props.title}
/>
</a>
);
}
}
export default ImageItem;
What am I doing wrong here?
You are not assigning the click handler to your component it should look like this :
class ImageItem extends Component {
render() {
return (
<a href="#" onClick={this.props.onClick}>
<img
className="portfolio-image"
src={this.props.image}
alt={this.props.title}
/>
</a>
);
}
}
export default ImageItem;

React.js search bar always fetches the same content

I'm building a search engine with React.js, where I can look for GIPHY gifs using their API. Everytime I type a word(any word), it always loads the same gifs and when I erase and write another word, the gifs don't update.
index.js:
import React from 'react'; //react library
import ReactDOM from 'react-dom'; //react DOM - to manipulate elements
import './index.css';
import SearchBar from './components/Search';
import GifList from './components/SelectedList';
class Root extends React.Component { //Component that will serve as the parent for the rest of the application.
constructor() {
super();
this.state = {
gifs: []
}
this.handleTermChange = this.handleTermChange.bind(this)
}
handleTermChange(term) {
console.log(term);
let url = 'http://api.giphy.com/v1/gifs/search?q=${term.replace(/\s/g, '+')}&api_key=aOfWv08Of7UqS6nBOzsO36NDvwYzO6io';
fetch(url).
then(response => response.json()).then((gifs) => {
console.log(gifs);
this.setState({
gifs: gifs
});
});
};
render() {
return (
<div>
<SearchBar onTermChange={this.handleTermChange} />
<GifList gifs={this.state.gifs} />
</div>
);
}
}
ReactDOM.render( <Root />, document.getElementById('root'));
search.js
import React, { PropTypes } from 'react'
import './Search.css'
class SearchBar extends React.Component {
onInputChange(term) {
this.props.onTermChange(term);
}
render() {
return (
<div className="search">
<input placeholder="Enter text to search for gifs!" onChange={event => this.onInputChange(event.target.value)} />
</div>
);
}
}
export default SearchBar;
Giflist:
import React from 'react';
import GifItem from './SelectedListItem';
const GifList = (props) => {
console.log(props.gifs);
const gifItems = props.gifs && props.gifs.data && props.gifs.data.map((image) => {
return <GifItem key={image.id} gif={image} />
});
return (
<div className="gif-list">{gifItems}</div>
);
};
export default GifList;
GifItem:
import React from 'react';
const GifItem = (image) => {
return (
<div className="gif-item">
<img src={image.gif.images.downsized.url} />
</div>
)
};
export default GifItem;
I can't seem to find where is the issue here. Is it because of this.handleTermChange = this.handleTermChange.bind(this) and there is no "update" state after?
Any help is welcome :) Thanks!
Its because, you are not putting the term value entered by user in the url, all the time you hit the api with static value term, here:
'http://api.giphy.com/v1/gifs/search?q=${term.replace(/\s/g, '+')}&api_key=aOfWv08Of7UqS6nBOzsO36NDvwYzO6io';
Replace ' by ' (tick), like this:
let url = `http://api.giphy.com/v1/gifs/search?q=${term.replace(/\s/g, '+')}&api_key=aOfWv08Of7UqS6nBOzsO36NDvwYzO6io`;
Check MDN Doc for more details about Template Literals.

Categories

Resources