React tutorial via PluralSight - props is not defined - javascript

I've been following a React tutorial on PluralSight when I ran into an error. Could be mine, I don't know.
I've been using JS Complete. The tutorial directed me to this URL, which is the starting point:
https://jscomplete.com/playground/rgs2.4
As the tutorial progressed, it led me to the following code:
const testData = [
{name: "Dan Abramov", avatar_url: "https://avatars0.githubusercontent.com/u/810438?v=4", company: "#facebook"},
{name: "Sophie Alpert", avatar_url: "https://avatars2.githubusercontent.com/u/6820?v=4", company: "Humu"},
{name: "Sebastian Markbåge", avatar_url: "https://avatars2.githubusercontent.com/u/63648?v=4", company: "Facebook"},
];
const CardList = (props) => (
<div>
{props.profiles.map(profile => <Card {...profile}/>)}
</div>
);
class Card extends React.Component {
render() {
const profile = this.props;
return (
<div className="github-profile">
<img src={profile.avatar_url} />
<div className="info">
<div className="name">{profile.name}</div>
<div className="company">{profile.company}</div>
</div>
</div>
);
}
}
class Form extends React.Component {
render() {
return (
<form action="">
<input type="text" placeholder="GitHub username" />
<button>Add Card</button>
</form>
);
}
}
class App extends React.Component {
constructor() {
super(props);
this.state = {
profiles: testData,
};
}
render() {
return (
<div>
<div className="header">{this.props.title}</div>
<Form />
<CardList profiles={this.state.profiles} />
</div>
);
}
}
ReactDOM.render(
<App title="The GitHub Cards App" />,
mountNode,
);
On the JS Complete site, it prints the error as follows:
ReferenceError: props is not defined
at new App
at constructClassInstance
at updateClassComponent
at beginWork$1
at HTMLUnknownElement.callCallback
at HTMLUnknownElement.sentryWrapped
at Object.invokeGuardedCallbackDev
at invokeGuardedCallback
at beginWork$$1
at performUnitOfWork
I would like to say I followed the tutorial exactly as instructed, but maybe I need a set of new eyes. I'm new to React.

You forgot to put the props in the constructor method
App extends React.Component {
constructor() {...
should be
App extends React.Component {
constructor(props) {...

Please find below the updated working code,
Observed that you are not passing the props from like title and referring from CardList
const CardList = (props) => (
<div>
{props.testData.map(profile => <Card {...profile}/>)}
</div>
);
class Card extends React.Component {
render() {
const profile = this.props;
return (
<div className="github-profile">
<img src={profile.avatar_url} />
<div className="info">
<div className="name">{profile.name}</div>
<div className="company">{profile.company}</div>
</div>
</div>
);
}
}
class App extends React.Component {
render() {
return (
<div>
<div className="header">{this.props.title}</div>
<CardList testData={this.props.data}/>
</div>
);
}
}
const testData = [
{name: "Dan Abramov", avatar_url: "https://avatars0.githubusercontent.com/u/810438?v=4", company: "#facebook"},
{name: "Sophie Alpert", avatar_url: "https://avatars2.githubusercontent.com/u/6820?v=4", company: "Humu"},
{name: "Sebastian Markbåge", avatar_url: "https://avatars2.githubusercontent.com/u/63648?v=4", company: "Facebook"},
];
ReactDOM.render(
<App title="The GitHub Cards App" data={testData}/>,
mountNode,
);

Related

Adding an Object to an Object's Array and setting the state in React

I am new at React and I come up with an Idea for learning many things in one shot. I have this component, Its initial state is an array with an object of baseball Players, I need to add new baseball Player's name through an Input field to the state and then, once a baseball Player is added, a second component appears with input fields to add data.
How can I do that?
export default class BaseballPlayerList extends React.Component {
constructor() {
super();
this.state = {
baseBallPlayers: [
{
name: "Barry Bonds",
seasons: [
{
year: 1994,
homeRuns: 37,
hitting: 0.294
},
{
year: 1996,
homeRuns: 40,
hitting: 0.294
}
]
}
]
};
this.addPlayer = this.addPlayer.bind(this);
}
addPlayer(e) {
e.preventDefault();
const newPLayer = {
baseBallPlayers: this.state.baseBallPlayers.name,
seasons: []
};
console.log(newPLayer);
this.setState(prevState => ({
baseBallPlayers: [...prevState.baseBallPlayers, newPlayer]
}));
}
render() {
return (
<div>
<div>
<ul>
{this.state.baseBallPlayers.map((player, idx) => (
<li key={idx}>
<PlayerSeasonInfo player={player} />
</li>
))}
</ul>
</div>
<input value={this.state.baseBallPlayers.name} />
<button onClick={this.addPlayer}>AddPlayer</button>
</div>
);
}
}
export default class PlayerSeasonInfo extends Component {
constructor(props) {
super(props);
this.player = this.props.player;
}
render() {
return (
<div>
{this.player && (
<div>
<span>{this.baseBallPlayers.name}</span>
<span>
<input placeholder="year" />
<input placeholder="homeRuns" />
<input placeholder="hitting" />
<button>AddInfo</button>
</span>
</div>
)}
</div>
);
}
}
here do you have a working example: https://codesandbox.io/s/nervous-yonath-9u2d6
the problem was where you where storing the new name and how you where updating the whole players state.
hope the example helps!

React, how to access child's state from parent? no need to update parent's state

Hi I am pretty new to React and having really hard time wrapping my head around this whole state management and passing data through state and props. I do understand that the standard react way is to pass down data in a unidirectional way- from parent to child, which I have done so for all other components.
But I have this component called Book, which changes its 'shelf' state, based on user selection form 'read, wantToRead, currentlyReading, and none'. And in my BookList component which renders Book component, but it needs to be able to read Book's shelf state and render the correct books under sections called 'read, wantToRead, currentlyReading, and none'. And since in this case, Book component is being rendered from BookList component and BookList being the parent, i really cannot understand how to enable BookList to access Book's state?
BookList component:
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import Book from './Book'
class BookList extends Component {
render(){
const { books, shelf } = this.props
return (
<div className="list-books">
<div className="list-books-content">
<div className="list-books-title">
<h1>MyReads</h1>
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">None</h2>
{books.map((book)=> {
console.log(book)
if (shelf === ''){
return <div className="bookshelf-books">
{/* <BookStateless book= {book} /> */}
<Book book = {book} />
{/* <BookStateless book= {book} /> */}
</div>
}
})}
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Currently Reading</h2>
{books.map((book)=> {
if (shelf === 'currentlyReading'){
return <div className="bookshelf-books">
{/* <BookStateless book= {book} /> */}
<Book book = {book} />
</div>
}
// console.log(this.book.title, this.book.state)
})}
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Want to Read</h2>
{books.map((book)=> {
if (shelf === 'wantToRead'){
return <div className="bookshelf-books">
{/* <BookStateless book= {book} /> */}
<Book book = {book} />
{/* <BookStateless book= {book} /> */}
</div>
}
// console.log(this.book.title, this.book.state)
})}
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Read</h2>
{books.map((book)=> {
if (shelf === 'read'){
console.log(shelf)
return <div className="bookshelf-books">
{/* <BookStateless book= {book} /> */}
<Book book = {book} />
</div>
}
// console.log(this.book.title, this.book.state)
})}
</div>
</div>
<div className="open-search">
<Link to="/search">Add a book</Link>
</div>
</div>
)
}
}
export default BookList
Book component:
import React, { Component } from 'react'
// import * as BooksAPI from './BooksAPI'
import Select from 'react-select'
import 'react-select/dist/react-select.css'
class Book extends Component {
state={
// state can be read, none, want to read, or currently reading
shelf: ''
}
handleChange(e){
this.setState({ shelf: e['value'] })
console.log("this?", this)
}
render(){
const { book } = this.props
const { shelf } = this.state
console.log("book", book.state)
const options = [
{ value: 'currentlyReading', label: 'currentlyReading'},
{ value: 'wantToRead', label: 'wantToRead'},
{ value: 'read', label: 'read'},
{ value: 'none', label: 'none'}
]
return (
<li key={book.id}>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 188, backgroundImage: `url("${book.imageLinks.thumbnail}")` }}></div>
<div className="book-shelf-changer">
<Select
value=""
options={options}
onChange={(e)=>this.handleChange(e)}
/>
</div>
</div>
<div className="book-title">{book.title}</div>
<div className="book-authors">{book.authors}</div>
</div>
</li>
)
}
}
export default Book
in my app.js i have:
import React from 'react'
import * as BooksAPI from './BooksAPI'
import './App.css'
import Search from './Search'
import BookList from './BookList'
import Book from './Book'
import { Route } from 'react-router-dom'
class BooksApp extends React.Component {
state = {
books : []
}
componentDidMount(){
BooksAPI.getAll().then((books)=> {
this.setState({ books: books })
// console.log("bookstest",this)
})
}
render() {
return (
<div className="App">
<Route exact path="/" render={()=>(
<Book books={this.state.books} />
)} />
<Route path="/search" render={()=>(
<Search books={this.state.books} />
)} />
<Route path="/BookList" render={()=>(
<BookList books={this.state.books} />
)} />
</div>
)
}
}
export default BooksApp
Right now, when i open the booklist component in browser, i get no books because it's not picking up the state in any of the if statements here:
if (shelf === 'currentlyReading'){
return <div className="bookshelf-books">
}
Thank you so much in advance for reading through and, any help would be much appreciated!
Thank you!
You don't need to "access" the child's state, you can pass a callback handler from the parent to the child and when an event is triggered inside the child you can notify the parent through that event handler (callback).
I'll post a small example:
class Book extends React.Component {
handleClick = e => {
const { bookId, onToggleBook } = this.props;
onToggleBook(bookId);
};
render() {
const { name, isRead } = this.props;
return (
<div className={`${isRead && "read"}`} onClick={this.handleClick}>
<span>{name}</span>
{isRead && <i> - You read me</i> }
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
books: [
{
id: 1,
name: "book 1",
isRead: false
},
{
id: 2,
name: "book 2",
isRead: false
},
{
id: 3,
name: "book 3",
isRead: true
},
{
id: 4,
name: "book 4",
isRead: false
}
]
};
}
onToggleBookStatus = bookid => {
const { books } = this.state;
const nextBookState = books.map(book => {
if (book.id !== bookid) return book;
return {
...book,
isRead: !book.isRead
};
});
this.setState(prevState => ({ books: nextBookState }));
};
render() {
const { books } = this.state;
return (
<div>
<div>My Books</div>
{books.map(book => (
<Book
key={book.id}
isRead={book.isRead}
name={book.name}
bookId={book.id}
onToggleBook={this.onToggleBookStatus}
/>
))}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
.read {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
As you know, to pass something from the parent to the child, you use props. To get something from the child to the parent, you again use props, but this time you pass a function down to the child, and then the child calls that function.
So for example, you would modify the child's handle change function to something like this:
handleChange(e){
if (this.props.onShelfChanged) {
this.props.onShelfChanged(e.value);
}
this.setState({ shelf: e.value })
}
And then in the parent, you'll want to pass an onShelfChanged prop down to the book, so that you can get notified when the value changes. Something like this:
// in the render function
{books.map((book, index) =>
<Book book={book} onShelfChanged={() => this.childBookChanged(index)}
)};
And you'll need to create and fill out the childBookChanged function to do whatever updates you need to do.
One thing to be mindful of is that you don't want to be manually keeping the book and the bookshelf in sync. The Book is tracking some state of its own, and then you're passing that up and probably altering the state of the bookshelf. Keeping these in sync as your application grows can be a headache and a source of bugs. Instead, you should have one piece of code be in charge, which it looks like will likely be the bookshelf (since it's the topmost component that cares about this state). So most likely you'll want to remove the internal state from Book, and instead tell the book what to do via props.
If you need the Book component to sometimes work as a standalone and sometimes work inside a bookshelf, then you may need to do a bit more work to get it to support both a "controlled" and "uncontrolled" implementation, but it's still a good idea to move the state up for the controlled case. You can read more about controlled and uncontrolled components here and here

Passing data to parent - recipebook React

I am working on the recipe book app and trying to implement the edit entry function.
How it works is to input recipe name (e.g Pasta), followed by ingredients (e.g egg, flour, salt). The ingredients have to be input with commas and will be shown as a list.
Pasta
-Egg
-Flour
i can see that it is somewhat working, because i can see the new entries in the input text (e.g initially was egg,flour,salt -> egg,flour,salt,water) when i tried to edit it again.
However, the extra ingredients (in the above example: water) is not showing up in the list. Do i have to figure a way to re-render the list?
updates:
I think i know where the error might be. There is some issue passing the data and setting the state.
<EditRecipe recipe={this.props.recipe} editRecipe={this.editRecipe.bind(this, this.props.recipe.id, recipe)}/>
App.js
import React, { Component } from 'react';
// import logo from './logo.svg';
import './App.css';
import uuid from 'uuid';
import Modal from 'react-modal';
import RecipeList from './components/RecipeList/RecipeList';
import AddRecipe from './components/AddRecipe/AddRecipe';
class App extends Component {
constructor(props){
super(props);
this.state = {
recipes:[]
};
}
getRecipes(){
this.setState({recipes:[
{
id: uuid.v4(),
food: "pumpkin pie",
ingredients: ["pumpkin puree", "sweetened condensed milk", "eggs", "pumpkin pie spice", "pie crust"]
},
{
id: uuid.v4(),
food: "spaghetti",
ingredients: ["noodles", "tomato sauce", "meatballs"]
},
{
id: uuid.v4(),
food: "onion pie",
ingredients: ["onion", "pie crust"]
},
]});
}
componentWillMount(){
this.getRecipes();
}
handleAddRecipe(recipe){
let recipes = this.state.recipes;
recipes.push(recipe);
this.setState({recipes: recipes});
}
handleDeleteRecipe(id){
let recipes = this.state.recipes;
let index = recipes.findIndex(x => x.id === id);
recipes.splice(index,1);
this.setState({recipes: recipes});
}
handleEditRecipe(id, recipe){
let recipes = this.state.recipes;
let index = recipes.findIndex(x => x.id === id);
recipes.splice(index,1,recipe);
this.setState({recipes: recipes});
}
render() {
return (
<div className="App">
<RecipeList recipes={this.state.recipes} onDelete={this.handleDeleteRecipe.bind(this)} onEdit={this.handleEditRecipe.bind(this)}/>
<AddRecipe addRecipe={this.handleAddRecipe.bind(this)}/>
</div>
);
}
}
export default App;
RecipeList.js
import React, { Component } from 'react';
import Collapsible from 'react-collapsible';
import RecipeItem from '../RecipeItem/RecipeItem'
import './RecipeList.css';
class RecipeList extends Component{
deleteRecipe(id){
this.props.onDelete(id);
}
editRecipe(id, recipe){
this.props.onEdit(id, recipe);
}
render(){
let recipeItem;
if(this.props.recipes){
recipeItem=this.props.recipes.map(recipe => {
return(
<RecipeItem onEdit={this.editRecipe.bind(this)} onDelete={this.deleteRecipe.bind(this)} key={recipe.id} recipe={recipe} />
)
});
}
return(
<div className="recipeList box">
{recipeItem}
</div>
)
}
}
export default RecipeList;
RecipeItem.js
import React, { Component } from 'react';
import Collapsible from 'react-collapsible';
import EditRecipe from '../EditRecipe/EditRecipe';
class RecipeItem extends Component{
deleteRecipe(id){
this.props.onDelete(id);
}
editRecipe(id, recipe){
this.props.onEdit(id, recipe);
}
render(){
let recipe=this.props.recipe
let foodName=recipe.food;
let ingredientItem;
if(recipe.ingredients){
ingredientItem=recipe.ingredients.map(ingredient=>{
return(
<a className="panel-block">
{ingredient}
</a>
)
})
}
return(
<ul>
<li className="Recipe">
<Collapsible trigger={foodName} transitionTime="200" easing="ease-in-out">
<nav className="panel">
<p className="panel-heading">
Ingredients
</p>
{ingredientItem}
<div className="panel-block">
<button className="button is-warning is-outlined" onClick={this.deleteRecipe.bind(this, this.props.recipe.id)}>
Delete
</button>
<EditRecipe recipe={this.props.recipe} editRecipe={this.editRecipe.bind(this, this.props.recipe.id, recipe)}/>
</div>
</nav>
</Collapsible>
</li>
</ul>
);
}
}
export default RecipeItem;
EditRecipe.js
import React, { Component } from 'react';
import RecipeForm from '../RecipeForm/RecipeForm';
// import './EditRecipe.css';
import Modal from 'react-modal';
import uuid from 'uuid';
// import Modal from 'boron/DropModal';
// import './RecipeList.css';
class RecipeEdit extends Component{
constructor(props){
super(props);
this.state = {
revisedRecipe:{
id: this.props.recipe.id,
food: this.props.recipe.food,
ingredients: this.props.recipe.ingredients
},
modalIsOpen: false,
speed: 100
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
}
openModal(){
this.setState({modalIsOpen: true});
}
closeModal(){
this.setState({modalIsOpen: false});
}
handleSubmit(e){
const revised = this.state.revisedRecipe;
this.props.editRecipe(revised);
e.preventDefault();
}
handleNameChange(e){
this.setState({revisedRecipe:{
food: e.target.value
}
});
}
handleIndChange(e){
this.setState({revisedRecipe:{
ingredients: e.target.value
}
});
}
render(){
const speed = this.state.speed;
let recipe=this.props.recipe;
let foodName=this.state.revisedRecipe.food;
let ingredients=recipe.ingredients;
return(
<div>
<button className="button is-primary" onClick={this.openModal}>Edit Recipe</button>
<Modal
isOpen={this.state.modalIsOpen}
onAfterOpen={this.afterOpenModal}
onRequestClose={this.closeModal}
closeTimeoutMS={speed}
contentLabel="Example Modal"
>
<div className="field">
<h2 className="title is-2">Edit Recipe</h2>
<form>
<label className="label">Recipe</label>
<div className="control">
<input className="input" type="text" placeholder="Recipe Name" ref="recipeName" value={this.state.revisedRecipe.food} onChange={this.handleNameChange.bind(this)}/>
</div>
<div className="field">
<label className="label">Ingredients</label>
<div className="control has-icons-left has-icons-right">
<input className="input" type="text" placeholder="Enter ingredients. (if more than 1 ingredient, separate them with commas)" ref="ingredients" value={this.state.revisedRecipe.ingredients} onChange={this.handleIndChange.bind(this)}/>
<span className="icon is-small is-left">
<i className="fa fa-flask"></i>
</span>
</div>
</div>
<div className="field is-grouped">
<div className="control">
<button className="button is-primary" onClick={this.closeModal}>Edit Recipe</button>
</div>
<div className="control">
<button className="button" onClick={this.closeModal}>Cancel</button>
</div>
</div>
</form>
</div>
</Modal>
</div>
);
}
}
export default RecipeEdit;
I believe you're actually getting an error when trying to re-render after updating a list. The ingredients property in the recipes are an array (as shown in getRecipes()) but you're setting the new state of ingredients (in EditRecipe) as a string: "egg,flour,salt,water" and then trying to render the ingredients as an array: ingredients.map().
When you render an input field with an array <input value={["egg", "flour"]} /> it does show the values separated by comma, but the event.target.value in onChange is actually a string.
In EditRecipe's, handleIndChange could be fixed with:
this.setState({revisedRecipe: {ingredients: e.target.value.split(',')}});
This does have another problem, though in that you are overriding the revisedRecipe completely. So all of the setState calls should be something like:
const recipe = this.state.revisedRecipe;
recipe.ingredients = e.target.value.split(',');
this.setState({revisedRecipe: recipe);

How to render an array of objects in React?

could you please tell me how to render a list in react js.
I do like this
https://plnkr.co/edit/X9Ov5roJtTSk9YhqYUdp?p=preview
class First extends React.Component {
constructor (props){
super(props);
}
render() {
const data =[{"name":"test1"},{"name":"test2"}];
const listItems = data.map((d) => <li key={d.name}>{d.name}</li>;
return (
<div>
hello
</div>
);
}
}
You can do it in two ways:
First:
render() {
const data =[{"name":"test1"},{"name":"test2"}];
const listItems = data.map((d) => <li key={d.name}>{d.name}</li>);
return (
<div>
{listItems }
</div>
);
}
Second: Directly write the map function in the return
render() {
const data =[{"name":"test1"},{"name":"test2"}];
return (
<div>
{data.map(function(d, idx){
return (<li key={idx}>{d.name}</li>)
})}
</div>
);
}
https://facebook.github.io/react/docs/jsx-in-depth.html#javascript-expressions
You can pass any JavaScript expression as children, by enclosing it within {}. For example, these expressions are equivalent:
<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>
This is often useful for rendering a list of JSX expressions of arbitrary length. For example, this renders an HTML list:
function Item(props) {
return <li>{props.message}</li>;
}
function TodoList() {
const todos = ['finish doc', 'submit pr', 'nag dan to review'];
return (
<ul>
{todos.map((message) => <Item key={message} message={message} />)}
</ul>
);
}
class First extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [{name: 'bob'}, {name: 'chris'}],
};
}
render() {
return (
<ul>
{this.state.data.map(d => <li key={d.name}>{d.name}</li>)}
</ul>
);
}
}
ReactDOM.render(
<First />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Shubham's answer explains very well. This answer is addition to it as per to avoid some pitfalls and refactoring to a more readable syntax
Pitfall : There is common misconception in rendering array of objects especially if there is an update or delete action performed on data. Use case would be like deleting an item from table row. Sometimes when row which is expected to be deleted, does not get deleted and instead other row gets deleted.
To avoid this, use key prop in root element which is looped over in JSX tree of .map(). Also adding React's Fragment will avoid adding another element in between of ul and li when rendered via calling method.
state = {
userData: [
{ id: '1', name: 'Joe', user_type: 'Developer' },
{ id: '2', name: 'Hill', user_type: 'Designer' }
]
};
deleteUser = id => {
// delete operation to remove item
};
renderItems = () => {
const data = this.state.userData;
const mapRows = data.map((item, index) => (
<Fragment key={item.id}>
<li>
{/* Passing unique value to 'key' prop, eases process for virtual DOM to remove specific element and update HTML tree */}
<span>Name : {item.name}</span>
<span>User Type: {item.user_type}</span>
<button onClick={() => this.deleteUser(item.id)}>
Delete User
</button>
</li>
</Fragment>
));
return mapRows;
};
render() {
return <ul>{this.renderItems()}</ul>;
}
Important : Decision to use which value should we pass to key prop also matters as common way is to use index parameter provided by .map().
TLDR; But there's a drawback to it and avoid it as much as possible and use any unique id from data which is being iterated such as item.id. There's a good article on this - https://medium.com/#robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318
Try this below code in app.js file, easy to understand
function List({}) {
var nameList = [
{ id: "01", firstname: "Rahul", lastname: "Gulati" },
{ id: "02", firstname: "Ronak", lastname: "Gupta" },
{ id: "03", firstname: "Vaishali", lastname: "Kohli" },
{ id: "04", firstname: "Peter", lastname: "Sharma" }
];
const itemList = nameList.map((item) => (
<li>
{item.firstname} {item.lastname}
</li>
));
return (
<div>
<ol style={{ listStyleType: "none" }}>{itemList}</ol>
</div>
);
}
export default function App() {
return (
<div className="App">
<List />
</div>
);
}
import React from 'react';
class RentalHome extends React.Component{
constructor(){
super();
this.state = {
rentals:[{
_id: 1,
title: "Nice Shahghouse Biryani",
city: "Hyderabad",
category: "condo",
image: "http://via.placeholder.com/350x250",
numOfRooms: 4,
shared: true,
description: "Very nice apartment in center of the city.",
dailyPrice: 43
},
{
_id: 2,
title: "Modern apartment in center",
city: "Bangalore",
category: "apartment",
image: "http://via.placeholder.com/350x250",
numOfRooms: 1,
shared: false,
description: "Very nice apartment in center of the city.",
dailyPrice: 11
},
{
_id: 3,
title: "Old house in nature",
city: "Patna",
category: "house",
image: "http://via.placeholder.com/350x250",
numOfRooms: 5,
shared: true,
description: "Very nice apartment in center of the city.",
dailyPrice: 23
}]
}
}
render(){
const {rentals} = this.state;
return(
<div className="card-list">
<div className="container">
<h1 className="page-title">Your Home All Around the World</h1>
<div className="row">
{
rentals.map((rental)=>{
return(
<div key={rental._id} className="col-md-3">
<div className="card bwm-card">
<img
className="card-img-top"
src={rental.image}
alt={rental.title} />
<div className="card-body">
<h6 className="card-subtitle mb-0 text-muted">
{rental.shared} {rental.category} {rental.city}
</h6>
<h5 className="card-title big-font">
{rental.title}
</h5>
<p className="card-text">
${rental.dailyPrice} per Night · Free Cancelation
</p>
</div>
</div>
</div>
)
})
}
</div>
</div>
</div>
)
}
}
export default RentalHome;
Try this:
class First extends React.Component {
constructor (props){
super(props);
}
render() {
const data =[{"name":"test1"},{"name":"test2"}];
const listItems = data.map((d) => <li key={d.name}>{d.name}</li>;
return (
<div>
{listItems}
</div>
);
}
}

Passing properties through components in ReactJS, ES6 example

I'm new to React and need some help. I'm trying to rewrite this Facebook's offical example into something own in ES6:
http://codepen.io/gaearon/pen/rrJNJY?editors=0010#0
My code looks like this:
class Person extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>{this.props.user.name}</h3>
<h4>{this.props.user.surname}</h4>
<h4>{this.props.user.age}</h4>
</div>
)
}
}
class VisualAppearance extends Component {
render() {
return(
<div>
<p>{this.props.user.visuals.eyes}</p>
<p>{this.props.user.visuals.height}</p>
<p>{this.props.user.visuals.hair}</p>
</div>
);
}
}
class CreatePerson extends Component {
render() {
return(
<div>
<h1>Personal Info: </h1>
<Person user={this.props.user}/>
<h1>Visual Appearance: </h1>
<VisualAppearance user={this.props.user}/>
<h1>Time Created:</h1>
<p>{this.props.dateCreated}</p>
</div>
);
}
}
var use = {
user: {
name: 'Dude',
surname: 'Dude Surname',
age: 30,
visuals: {
eyes: 'blue',
height: 180,
hair: 'dark'
}
},
dateCreated: new Date()
}
ReactDOM.render(
<CreatePerson name={use.user.name}
surname={use.user.surname} age={use.user.age} eyes={use.user.visuals.eyes} height={use.user.visuals.height}
hair={use.user.visuals.height} date={use.user.dateCreated}
/>
, document.getElementById('project'));
I get the following error: Cannot read property 'name' of undefined
If I change this just to this.props.user it goes through but the same error as above is reported on the surname.
In the link provided there is: props.user.avatarUrl , so it's a nested structure of the object.
How can I make this work and nesting object's properties like this.props.sth.sthElse.sthElse1 on ES6 Classes in React?
CreatePerson expects a property called user here:
class CreatePerson extends Component {
render() {
return(
<div>
<h1>Personal Info: </h1>
<Person user={this.props.user}/> // <====
<h1>Visual Appearance: </h1>
<VisualAppearance user={this.props.user}/> // <====
<h1>Time Created:</h1>
<p>{this.props.dateCreated}</p>
</div>
);
}
}
You're not passing it one. You're passing it name, surname, and a bunch of others, but not user.
It works if you remove all those individual properties and pass it user instead:
ReactDOM.render(
<CreatePerson user={use.user} />
, document.getElementById('project'));
Example:
class Person extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>{this.props.user.name}</h3>
<h4>{this.props.user.surname}</h4>
<h4>{this.props.user.age}</h4>
</div>
)
}
}
class VisualAppearance extends React.Component {
render() {
return(
<div>
<p>{this.props.user.visuals.eyes}</p>
<p>{this.props.user.visuals.height}</p>
<p>{this.props.user.visuals.hair}</p>
</div>
);
}
}
class CreatePerson extends React.Component {
render() {
return(
<div>
<h1>Personal Info: </h1>
<Person user={this.props.user}/>
<h1>Visual Appearance: </h1>
<VisualAppearance user={this.props.user}/>
<h1>Time Created:</h1>
<p>{this.props.dateCreated}</p>
</div>
);
}
}
var use = {
user: {
name: 'Dude',
surname: 'Dude Surname',
age: 30,
visuals: {
eyes: 'blue',
height: 180,
hair: 'dark'
}
},
dateCreated: new Date()
}
ReactDOM.render(
<CreatePerson user={use.user} />
, document.getElementById('project'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="project"></div>

Categories

Resources