Displaying Multiple Properties of a component in React - reactjs

I'm a beginner, learning React using this tutorial as a guide > http://survivejs.com/webpack_react/implementing_notes/
I'm having trouble understanding and figuring out how to make a shopping list with product name, sku, and price as the properties. I know how to pass one property from the tutorial, but multiple properties of a component i'm not sure what I'm doing wrong.
My problem is only the product name is showing on the page. I need the sku and price to show as well, but not understanding how those are not being passed along.
My best assumption is in item.jsx, it is only passing the product and not sku and price so how do I do that?
the export default ({product}) => <div>{product}</div>;
This is how my components are layed out.
APP Component > Lists Component > List Component
App.jsx
import uuid from 'node-uuid'
import React from 'react';
import Items from './Items.jsx';
export default class APP extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [
{
id: uuid.v4(),
product: 'apples',
sku: '1234',
price: '23.99'
},
{
id: uuid.v4(),
product: 'oranges',
sku: '2345',
price: '24.99'
},
{
id: uuid.v4(),
product: 'strawberries',
sku: '3456',
price: '25.99'
}
]
};
}
render() {
const items = this.state.items;
return (
<div>
<button onClick={this.addItem}>+</button>
<Items items={items} />
</div>
);
}
}
Items.jsx
import React from 'react';
import Item from './item.jsx';
export default ({items}) => {
return (
<ul>{items.map(item =>
<li key={item.id}>
<Item
product={item.product}
sku={item.sku}
price={item.price} />
</li>
)}</ul>
);
}
Item.jsx
export default ({product}) => <div>{product}</div>;

You are correctly passing the properties along - You can see this in your Items.jsx file here:
<Item
product={item.product}
sku={item.sku}
price={item.price}
/>
However, in your Item.jsx file, you're not printing the properties out. It may be a little easier to understand if you write your Item.jsx file as your have written your App.jsx file:
export default class Item extends React.Component {
render() {
return (
<div>
{this.props.product}, {this.props.sku}, {this.props.price}
</div>
)
}
}
Instead of passing it as a param of a function, you can reference the properties you pass in using this.props.{propName} - it's a more widely used way of writing React components, and it looks like the tutorial you're using goes on to using React props a little further down the page.

You're using a stateless function component, which is a function that receives props as a parameter. You can actually write it like this:
export default (props) => (
<div>
<span>{ this.props.product }</span>
<span>{ this.props.sku }</span>
<span>{ this.props.price }</span>
</div>;
);
However, since ES6 supports destructuring assignment on objects, we can assign the props object properties to variables:
export default ({ product, sku, price }) => (
<div>
<span>{ product }</span>
<span>{ sku }</span>
<span>{ price }</span>
</div>;
);

Related

this.props react training Question - CodeAcademy

I'm going through CodeCademy React beginner training. I just finished a short chapter on props and passing props, and I'm still very confused on the topic and wanted to do some more reviewing on this. CodeCademy had the below question as a "quiz", I submitted my answer - it told me it was wrong and didn't give me an explanation or solution.
Could someone please answer this question for me and maybe provide me a good guide to review the react props.
Question: Pass in the item, quantity, price of an item as props from the App component to the shopping cart component. These values will be rendered within the corresponding list elements. The item prop should contain the string “Apple”, the quantity prop should contain the number 3, and the price prop should contain the number 1.99.
import React from 'react';
import ReactDOM from 'react-dom';
export class App extends React.Component {
render() {
return (
<ShoppingCart />
);
}
}
export class ShoppingCart extends React.Component {
render() {
return <ul>
<li>Item: {this.props.item}</li>
<li>Quantity: {this.props.quantity}</li>
<li>Price: {this.props.price}</li>
</ul>;
}
Thank you
If I understand well, the shopping cart should expect an array of items, ie: <ShoppingCart items={[]} />. Then inside the shopping cart, you map over the received items.
Then, I think the excepted answer should look like this:
import React from 'react';
export class App extends React.Component {
render() {
return (
<ShoppingCart items={[{ item: 'Apple', quantity: 3, price: 1.99 }]} />
);
}
}
export class ShoppingCart extends React.Component {
render() {
return (
<div>
{this.props.items.map(item => (
<ul key={JSON.stringify(item)}>
<li>Item: {item.item}</li>
<li>Quantity: {item.quantity}</li>
<li>Price: {item.price}</li>
</ul>))
}
</div>
);
}
You are not passing the props to the ShoppingCart component when trying to render it from App class.
do the below, to correct it
export class App extends React.Component {
render() {
return (
<ShoppingCart item="Apple" quantity={3} price={1.99} />
);
}
}

Is there a way in React Javascript to pass props and use it in external import?

I want to pass props from one component to another, and use it in the second one for an import above the component declaration
This is for using the same component, with no need to create it 4 times, every time with another SVG.
I'm using React, Javascript, Webpack, babel.
I'm also using svgr/webpack to create a component from an SVG picture, and it's crucial for me to use SVG not < img >.
import React from 'react';
import RightNavItem from './right_nav_item';
const RightNav = ({navitems}) => {
const rightNavItems = navitems.map( (item) => {
return <RightNavItem name={ item }/>
});
return(
<div className="rightnav">
{rightNavItems}
</div>
);
};
.
export default RightNav;
import React from 'react';
const RightNavItem = ({ name }) => {
const svgpath = `../../../../resources/img/navbar/${name}.svg`;
return(
<div>
<img src={ svgpath } style={{height: '25px'}}/>
<span>{ name }</span>
</div>
);
};
export default RightNavItem;
And I want to achieve being able to do this:
import React from 'react';
import SvgPicture from '../../../../resources/img/navbar/{name}.svg';
const RightNavItem = ({ name }) => {
return(
<div>
<SvgPicture />
<span>{ name }</span>
</div>
);
};
export default RightNavItem;
.
Ok so I went back and implemented the whole thing on my local app to get exactly what you need. I am editing my original answer. Hope this solves your issue.
The parent:
import React from 'react';
import { ReactComponent as svg } from 'assets/img/free_sample.svg';
import RightNavItem from './RightNavItem';
const LOGOS = [
{ name: 'home', svg },
{ name: 'home', svg },
];
const RightNav = () => (
<div>
{LOGOS.map(logo => (
<RightNavItem name={logo.name}>
<logo.svg />
</RightNavItem>
))}
</div>
);
export default RightNav;
The child:
import React from 'react';
const RightNavItem = ({ name, children }) => (
<div>
{children}
<span>{name}</span>
</div>
);
export default RightNavItem;
You don't need to import the svg as I did, if you are able to use svg as a component in your webpack config then continue to do what you were doing before.
I managed to do it in a kind of ugly way, but it works.
The problem is if I have more than 4 items, then using it without the map() function can be really annoying.
I used {props.children}, and instead of using map(), I added the 4 times, each with different 'SVG' component child and different props 'name', that way the component only gets initialized at the RightNavItem level.
IF SOMEONE KNOWS how can I use this with the map() function, It'll help a lot!
Thanks to everyone who helped!
For example:
const RightNav = (props) => {
return(
<div className = "rightnav">
<RightNavItem name = {home}>
<HomeSVG />
</RightNavItem>
<RightNavItem name = {profile}>
<ProfileSVG />
</RightNavItem>
.
.
.
</div>
);
};
And in the RightNavItem:
const RightNavItem = (props) => {
return(
<div>
{props.children}
<span>{ props.name }</span>
</div>
);
};

TypeError: robots.map is not a function

I keep getting this error: TypeError: robots.map is not a function.
I reviewed the code several times can't find the bug.
import React from 'react';
import Card from './Card';
// import { robots } from './robots';
const CardList = ({ robots }) => {
return(
<div>
{
robots.map((user, i) => {
return (
<Card
key={i}
id={robots[i].id}
name={robots[i].name}
email={robots[i].email}
/>
);
})
}
</div>
);
}
export default CardList;
App.js
import React, { Component } from 'react';
import CardList from './CardList';
import SearchBox from './SearchBox';
import { robots } from './robots';
class App extends Component {
constructor(){
super()
this.state = {
robots:'robots',
searchfield: ''}
}
render(){
return(
<div className='tc'>
<h1 className=''>RoboFriends</h1>
<SearchBox />
<CardList robots={this.state.robots}/>
</div>
);
}
}
export default App;
I updated the initial code with App.js that calls CardList.
I recently started learning react and I hope to develop an app that lets you search for a user which instantly filters and render the name typed in the search box.
You pass robots as props from App internal state and not from the imported file.
Set the state of App component from the imported robots file
import { robots } from './robots'
class App extends Component {
constructor() {
super()
this.state = {
robots,
searchfield: ''
}
}
render() {
return (
<div className='tc'>
<h1 className=''>RoboFriends</h1>
<SearchBox />
<CardList robots={this.state.robots}/>
</div>
);
}
}
Also using index as React key is a bad practice, You have a unique id in every robot object so use it as key, also read about the map function and how to access the iterated elements
const CardList = ({ robots }) => (
<div>
{robots.map(robot => (
<Card
key={robot.id}
id={robot.id}
name={robot.name}
email={robot.email}
/>
))}
</div>
);
You're passing a string to be mapped, instead pass the robots list of objects and see the result.
These kind of errors are the result of passing something other than a list to be mapped

react mapping over array of objects

My current state is an array of objects. I am mapping over them and I am getting exactly what I want. However, inside of my array of objects I am not receiving the ingredients that I want. I am receiving the console.log of that value but the value it self I am not displaying anything on the dom. Heres my code. I am trying to have my ingredients show up inside of the li that I am mapping but when I click on my panels I am receiving no value. However, my console.log below it shows a value. idk...
import React from 'react';
import Accordian from 'react-bootstrap/lib/Accordion';
import Panel from 'react-bootstrap/lib/Panel';
import Button from 'react-bootstrap/lib/Button';
import ButtonToolbar from 'react-bootstrap/lib/ButtonToolbar';
import Modal from 'react-bootstrap/lib/Modal';
import FormGroup from 'react-bootstrap/lib/FormGroup';
import ControlLabel from 'react-bootstrap/lib/ControlLabel';
import FormControl from 'react-bootstrap/lib/FormControl';
export default class App extends React.Component {
constructor () {
super();
this.state = {recipes: [
{recipeName: 'Pizza', ingredients: ['Dough', 'Cheese', 'Sauce']},
{recipeName: 'Chicken', ingredients: ['Meat', 'Seasoning', 'other']},
{recipeName: 'Other', ingredients: ['other1', 'other2', 'other3']}
]};
console.log(this.state.recipes);
}
render() {
const recipes = this.state.recipes.map((recipe, index) => {
return (
<Panel header={recipe.recipeName} eventKey={index} key={index}>
<ol>
{recipe.ingredients.map((ingredient) => {
<li> {ingredient} </li>
console.log(ingredient);
})}
</ol>
</Panel>
)
});
return (
<div className="App container">
<Accordian>
{recipes}
</Accordian>
</div>
)
}
}
Because you are not returning anything from inner map body.
Write it like this:
{recipe.ingredients.map((ingredient) => {
console.log(ingredient);
return <li key={...}> {ingredient} </li> //use return here
})}
Or you can simply write it like this:
{
recipe.ingredients.map((ingredient) => <li key={...}> {ingredient} </li>)
}
As per MDN Doc:
Arrow functions can have either a "concise body" or the usual "block
body".
In a concise body, only an expression is needed, and an implicit
return is attached. In a block body, you must use an explicit return
statement.
Check MDN Doc for more details about Arrow Function.

Conditional List in ReactJS Based On State

I am pretty new to React JS and I am just wondering how I can filter what my component renders based on the state of my prop.
So I have the following component that allows me to select a certain brand and store it as a prop:
var React = require('react');
import Select from 'react-select';
class VehicleSelect extends React.Component {
constructor(props) {
super(props);
this.state = { brandSelect: ""};
}
_onChange(value) {
//console.log(value) - just to see what we recive from <Select />
this.setState({brandSelect: value}, () => {
console.log(this.state.brandSelect);
});
}
render() {
var options = [
{ value: 'Volkswagen', label: 'Volkswagen' },
{ value: 'SEAT', label: 'SEAT' },
{ value: 'SKODA', label: 'SKODA' }
];
return (
<Select
name="form-field-name"
value={this.state.brandSelect}
options={options}
placeholder="Select a brand"
searchable={false}
onChange={this._onChange.bind(this)}
/>
)
}
};
// Export our component
export default VehicleSelect;
This component works as expected however I am having issues when it comes to taking the brandSelect prop and conditionally deciding what my component should render.
Here is my details component:
var React = require('react');
import { If, Then, Else } from 'react-if';
import VehicleSelect from './vehicle-select.js';
// Vehicle Description Component
const VehicleDetail = (props) => {
return (
<If condition={ this.state.brandSelect === props.vehicle.brand.name }>
<div className="col-flex-md-3 col-flex-sm-4 col-flex-xs-6 col-flex-media-query">
<div className="vehicle-container">
<img src={"https://s3-eu-west-1.amazonaws.com/pulman-vw-images/uploads/images/thumbnails/" + props.vehicle.offers[0].image.name} />
<h4 className="vehicle-title">
{props.vehicle.model.name}
</h4>
<div className="row-flex">
<div className="col-flex-xs-12 btn-container">
Learn More
</div>
</div>
</div>
</div>
</If>
);
};
// Export our component
export default VehicleDetail;
As you can see it constructs a HTML container with data. I have also added a conditional statement (react-if on GitHub) to try and render data that matches the option that was selected in my VehicleSelect component however this doesn't seem to work. I get the following error:
Warning: There is an internal error in the React performance measurement code. Did not expect componentDidUpdate timer to start while render timer is still in progress for another instance.
Here is my component that iterates over my VehicleDetail component and supplies data to it:
var React = require('react');
// Vehicle List Componen
import VehicleDetail from './vehicle-detail.js';
// Create our component
const VehicleList = (props) => {
// Just add props.vehicle to access API data instead of static
const RenderedVehicles = props.vehicles.map(vehicle =>
<VehicleDetail key={vehicle.slug} vehicle={vehicle} />
);
return (
<div className="row-flex center-xs">
{RenderedVehicles}
</div>
);
};
// Export our component
export default VehicleList;
So my question is where am I going wrong? As I am new to ReactJS I am unsure how I can render components based on the state that has been selected. All I am trying to do is show data that matches the brandSelect prop in my VehicleSelect component. If the brandSelect prop is equals "" then I would like to render all of the data that is mapped in my VehicleList component.
Thanks
You cannot use this.state.brandSelect in the Details component
Since your details component is setup and brandselect is present in the parent component too

Resources