I have defined some sample data (collection) and trying to iterate through but getting Failed to Compile and it's pointing to render() { in this component:
class RecipeList extends Component {
constructor(props) {
super(props);
this.state = {
recipes: {
"1": {
id: 1,
url: 'http://via.placeholder.com/300x300',
title: '1st Title',
description: 'some decription 1'
},
"1": {
id: 2,
url: 'http://via.placeholder.com/300x300',
title: '1st Title',
description: 'some decription 1'
},
"1": {
id: 3,
url: 'http://via.placeholder.com/300x300',
title: '1st Title',
description: 'some decription 1'
}
}
}
render() {
const recipeIds = Object.keys(this.state.recipes);
const Items = recipeIds.map((recipe) => {
return (
<RecipeListItem
key={recipe}
recipe={recipe}
/>
);
});
return (
<div>
{Items}
</div>
);
}
}
You need unique keys for your recipes. Try the following
class RecipeList extends Component {
constructor(props) {
super(props);
this.state = {
recipes: {
"1": {
id: 1,
url: 'http://via.placeholder.com/300x300',
title: '1st Title',
description: 'some decription 1'
},
"2": {
id: 2,
url: 'http://via.placeholder.com/300x300',
title: '1st Title',
description: 'some decription 1'
},
"3": {
id: 3,
url: 'http://via.placeholder.com/300x300',
title: '1st Title',
description: 'some decription 1'
}
}
}
}
render() {
const recipeIds = Object.keys(this.state.recipes);
const Items = recipeIds.map((key) => {
return (
<div
key={key}>
{this.state.recipes[key].id}
</div>
);
});
return (
<div>
{Items}
</div>
);
}
}
Edit: Updated the code to provide the whole class.
Related
This is shop page.jsx file here i want to show the list of filtered items at the top of the page. Here im using data list for getting all the details. Here i want to show length of filtered products at showing 9 0f 9 products.
import React, { useEffect, useState } from 'react';
import EmptyView from '../components/common/EmptyView';
import FilterPanel from '../components/Home/FilterPanel';
import List from './Home/List';
// import SearchBar from '../../components/Home/SearchBar';
import { dataList } from '../constants';
// import './styles.css';
import '../App.css';
import ButtonAppBar from "./Header";
const Shop = () => {
// const [selectedCategory, setSelectedCategory] = useState(null);
// const [selectedRating, setSelectedRating] = useState(null);
const [selectedPrice, setSelectedPrice] = useState([0, 150]);
const [cuisines, setCuisines] = useState([
{ id: 1, checked: false, label: 'Furniture' },
{ id: 2, checked: false, label: 'Decoration' },
{ id: 3, checked: false, label: 'Bedding' },
{ id: 4, checked: false, label: 'Lighting' },
{ id: 5, checked: false, label: 'Bath&Shower' },
{ id: 6, checked: false, label: 'Curtains' },
{ id: 7, checked: false, label: 'Toys' },
]);
const [brand, setBrand] = useState([
{ id: 1, checked: false, label: 'Poliform' },
{ id: 2, checked: false, label: 'Rochie Bobois' },
{ id: 3, checked: false, label: 'Edra' },
{ id: 4, checked: false, label: 'Kartell' },
]);
const [availability, setAvailability] = useState([
{ id: 1, checked: false, label: 'Onstock' },
{ id: 2, checked: false, label: 'Outofstock' },
]);
const [list, setList] = useState(dataList);
const [resultsFound, setResultsFound] = useState(true);
// const [searchInput, setSearchInput] = useState('');
// const handleSelectCategory = (event, value) =>
// !value ? null : setSelectedCategory(value);
// const handleSelectRating = (event, value) =>
// !value ? null : setSelectedRating(value);
const handleChangeChecked = (id) => {
const cusinesStateList = cuisines;
const changeCheckedCuisines = cusinesStateList.map((item) =>
item.id === id ? { ...item, checked: !item.checked } : item
);
setCuisines(changeCheckedCuisines);
};
const handleChangeCheckeds = (id) => {
const brandStateList = brand;
const changeCheckedsBrand = brandStateList.map((item) =>
item.id === id ? { ...item, checked: !item.checked } : item
);
setBrand(changeCheckedsBrand);
};
const handleChangeCheckedss = (id) => {
const availabilityStateList = availability;
const changeCheckedssAvailability = availabilityStateList.map((item) =>
item.id === id ? { ...item, checked: !item.checked } : item
);
setAvailability(changeCheckedssAvailability);
};
const handleChangePrice = (event, value) => {
setSelectedPrice(value);
};
const applyFilters = () => {
let updatedList = dataList;
// // Rating Filter
// if (selectedRating) {
// updatedList = updatedList.filter(
// (item) => parseInt(item.rating) === parseInt(selectedRating)
// );
// }
// // Category Filter
// if (selectedCategory) {
// updatedList = updatedList.filter(
// (item) => item.category === selectedCategory
// );
// }
// Cuisine Filter
const cuisinesChecked = cuisines
.filter((item) => item.checked)
.map((item) => item.label.toLowerCase());
if (cuisinesChecked.length) {
updatedList = updatedList.filter((item) =>
cuisinesChecked.includes(item.cuisine)
);
}
// brand filter
const brandChecked = brand
.filter((item) => item.checked)
.map((item) => item.label.toLowerCase());
if (brandChecked.length) {
updatedList = updatedList.filter((item) =>
brandChecked.includes(item.brand)
);
}
// availabilty filter
const availabilityChecked = availability
.filter((item) => item.checked)
.map((item) => item.label.toLowerCase());
if (availabilityChecked.length) {
updatedList = updatedList.filter((item) =>
availabilityChecked.includes(item.availability)
);
}
// // Search Filter
// if (searchInput) {
// updatedList = updatedList.filter(
// (item) =>
// item.title.toLowerCase().search(searchInput.toLowerCase().trim()) !==
// -1
// );
// }
// // Price Filter
const minPrice = selectedPrice[0];
const maxPrice = selectedPrice[1];
updatedList = updatedList.filter(
(item) => item.price >= minPrice && item.price <= maxPrice
);
setList(updatedList);
!updatedList.length ? setResultsFound(false) : setResultsFound(true);
};
useEffect(() => {
applyFilters();
}, [cuisines, brand, availability, selectedPrice]);
return (
<div>
<ButtonAppBar />
<div className='home'>
{/* Search Bar */}
{/* <SearchBar
value={searchInput}
changeInput={(e) => setSearchInput(e.target.value)}
/> */}
<br /><br /><br /> <div className='home_panelList-wrap'>
{/* Filter Panel */}
<div className='home_panel-wrap'>
<FilterPanel
// selectedCategory={selectedCategory}
// selectCategory={handleSelectCategory}
// selectedRating={selectedRating}
selectedPrice={selectedPrice}
// selectRating={handleSelectRating}
cuisines={cuisines}
changeChecked={handleChangeChecked}
brand={brand}
changeCheckeds={handleChangeCheckeds}
availability={availability}
changeCheckedss={handleChangeCheckedss}
changePrice={handleChangePrice}
/>
</div>
{/* List & Empty View */}
<div className='home_list-wrap'>
<h6>Showing
<span style={{ color: "#bd744c" }}><b>{dataList.length}</b></span> of
<span style={{ color: "#bd744c" }}><b>9</b></span>
Products</h6>
{resultsFound ? <List list={list} /> : <EmptyView />}
</div>
</div>
</div>
</div>
);
};
export default Shop;
This is constant.js file from here we are getting all our details in shop.jsx file.
export const dataList = [
{
id: 1,
title: 'AwesomeLamp',
cuisine: 'lighting',
price: 40,
image: '/images/AwesomeLamp.png',
brand: 'poliform',
availability: 'onstock',
name: 'AwesomeLamp',
tagName: 'AwesomeLamp'
},
{
id: 2,
title: 'CozySofa',
cuisine: 'furniture',
price: 150,
image: '/images/CozySofa.png',
brand: 'edra',
availability: 'outofstock',
name: 'CozySofa',
tagName: 'CozySofa'
},
{
id: 3,
title: 'AwesomeCandle',
cuisine: 'lighting',
price: 15,
image: '/images/AwesomeCandle.png',
brand: 'kartell',
availability: 'onstock',
name: 'AwesomeCandle',
tagName: 'AwesomeCandle',
},
{
id: 4,
title: 'FancyChair',
cuisine: 'furniture',
price: 70,
image: '/images/FancyChair.png',
brand: 'poliform',
availability: 'outofstock',
name: 'FancyChair',
tagName: 'FancyChair'
},
{
id: 5,
title: 'ChineseTeapot',
cuisine: 'decoration',
price: 50,
image: '/images/ChineseTeapot.png',
brand: 'rochie bobois',
availability: 'onstock',
name: 'ChineseTeapot',
tagName: 'ChineseTeapot'
},
{
id: 6,
title: 'SoftPillow',
cuisine: 'bedding',
price: 30,
image: '/images/SoftPillow.png',
brand: 'edra',
availability: 'onstock',
name: 'SoftPillow',
tagName: 'SoftPillow'
},
{
id: 7,
title: 'WoodenCasket',
cuisine: 'decoration',
price: 20,
image: '/images/WoodenCasket.png',
brand: 'kartell',
availability: 'onstock',
name: 'WoodenCasket',
tagName: 'WoodenCasket'
},
{
id: 8,
title: 'AwesomeArmChair',
cuisine: 'furniture',
price: 90,
image: '/images/AwesomeArmChair.png',
brand: 'poliform',
availability: 'onstock',
name: 'AwesomeArmchair',
tagName: 'AwesomeArmchair'
},
{
id: 9,
title: 'CoolFlower',
cuisine: 'decoration',
price: 20,
image: '/images/CoolFlower.png',
brand: 'none',
availability: 'onstock',
name: 'CoolFlower',
tagName: 'CoolFlower'
},
];
What the fetch returns is a list of items. I want to add those into state.
const [state, setState] = useState({
list: {
items: [],
}
});
fetch('http://example.com/list/')
// GET response: [{ name: 'foo' }, { name: 'bar' }, { name: 'baz' }]
.then((resList) => resList.json())
.then((list) => {
list.forEach(({ name }) => {
const itemUrl = `https://example.com/list/${name}`;
fetch(itemUrl)
// GET responses:
// { name: 'foo', desc: '123' }
// { name: 'bar', desc: '456' }
// { name: 'baz', desc: '789' }
.then((itemRes) => itemRes.json())
.then((item) => {
setState((prevState) => ({
...prevState,
list: {
items: [...state.list.items, item]
},
});
})
})
}
})
console.log(state);
// result: [{ name: 'baz', desc: '789' }]
// but wanted: [{ name: 'foo', desc: '123' }, { name: 'bar', desc: '456' }, { name: 'baz', desc: '789' }]
In your case no need to use prevState in setState.
I prepared an example for you. Just be careful at using hooks.
https://codesandbox.io/s/recursing-wood-4npu1?file=/src/App.js:0-567
import React, { useState } from "react"
import "./styles.css"
export default function App() {
const [state, setState] = useState({
list: {
items: [
{ name: "foo", desc: "123" },
{ name: "bar", desc: "456" },
],
},
})
const handleClick = () => {
setState(() => ({
list: {
items: [...state.list.items, { name: "baz", desc: "789" }],
},
}))
}
return (
<div className="App">
<button onClick={handleClick}>Click Me </button>
<hr />
{JSON.stringify(state)}
</div>
)
}
You can't directly access the callback for useState hooks. This is how you can update state after fetching the data:
setState({
...state,
list: {
items:[...state.list.items, item]
},
});
I'm using devexpress React table and you can hide and show columns via state.
I would like to change the state for hidden from true to false but I get an Uncaught Invariant Violation error.
I've tried to use setState but doesn't work.
class ResultsTable extends Component {
constructor(props) {
super(props);
this.state = {
columns: [
{ name: 'agent', title: 'Agent' },
{ name: 'alertGroup', title: 'Alert Group', hidden:true },
{ name: 'manager', title: 'Manager', hidden:true }
],
};
}
componentDidMount() {
this.testAlert();
}
testAlert = () => {
if (this.props.alertgroupColumn()) {
this.setState({
columns: [{ name: 'alertGroup', title: 'Alert Group', hidden:false }]
})
}
}
Hidden should change from true to false.
I have another alternative to update your state
class ResultsTable extends Component {
constructor(props) {
super(props);
this.state = {
columns: [
{ name: 'agent', title: 'Agent' },
{ name: 'alertGroup', title: 'Alert Group', hidden:true },
{ name: 'manager', title: 'Manager', hidden:true }
],
};
}
componentDidMount() {
this.testAlert();
}
testAlert = () => {
if (this.props.alertgroupColumn()) {
//---- get the columns from state
let columns = JSON.parse(JSON.stringify(this.state.columns))
columns[1].hidden = false
this.setState({
columns:columns
})
this.setState({
columns: [{ name: 'alertGroup', title: 'Alert Group', hidden:false }]
})
}
}
I am trying to use this component: https://github.com/jrowny/react-absolute-grid.
The documentation says I should pass a displayObject which renders items.
So I created a displayObject, like the one in the docs which has this render method:
render: function() {
// Supposing your item shape is something like {name: 'foo'}
const { item, index, itemsLength } = this.props;
return <div>Item {index} of {itemsLength}: {item.name}</div>;
}
I passed it to the component like this:
<AbsoluteGrid
items={SampleData.screens}
displayObject={<DisplayObject/>}
onMove={onMoveDebounced}
dragEnabled={true}
responsive={true}
verticalMargin={42}
itemWidth={250}
itemHeight={250}
filteredProp={'name'}
/>
Where SampleData.screens is:
module.exports = {
screens: [
{'url': 'http://invisionapp.com/subsystems/do_ui_kit/assets/img/screens/original-1x/screen-1-1-login.jpg', 'name': 'login', 'sort': 1, 'key': 1},
{'url': 'http://invisionapp.com/subsystems/do_ui_kit/assets/img/screens/original-1x/screen-1-2-sign-up.jpg', 'name': 'signup', 'sort': 2, 'key': 2},
{'url': 'http://invisionapp.com/subsystems/do_ui_kit/assets/img/screens/original-1x/screen-1-3-walkthrough.jpg', 'name': 'walkthrough', 'sort': 3, 'key': 3}
]
};
When I open the page in the browser, I don't see the text from the displayObject.
How can I use the displayObject?
DisplayObject works good when is a function that return the render html, I try creating a different React.Component for it but got some issues
const items = [
{ key: "0", sort: 0, name: 'Test 1', filtered: false },
{ key: "1", sort: 1 ,name: 'Test 2', filtered: false },
{ key: "2",sort: 2, name: 'Test 3', filtered: false},
{ key: "3", sort: 3,name: 'Test 4', filtered: false }
]
function GridItem(props) {
const { item, index, itemsLength } = props;
return <div >
<span>{item.name}</span>
</div>;
}
const AbsoluteGrid = createAbsoluteGrid(GridItem);
In the browser console I get the object. But when I try and return just the text, link, title nothing returns. I get the object in the console, but when I try and add .text or .link the page shows blank. The console shows no errors.
import React, { Component } from 'react';
class Navigation extends Component {
getLinks = (object) => {
Object.keys(object).map((property, i) => {
const { text, title } = object[property][i];
console.log(object[property][i])
return (
<ul>{title}
<li>{text}</li>
</ul>
)
});
}
render() {
let { items } = this.props;
return (
<div>
<ul>
{this.getLinks(items)}
</ul>
</div>
);
}
}
export default Navigation;
JSON
const navigation = {
pageInfo: [
{title: "A title"},
{text: "item 1", link: "https://google.com"},
{text: " item 2", link: "https://googleconquestio.com"}
],
pageInfo2: [
{title: "A title"},
{text: "item 1", link: "https://google.com"},
{text: "item 2", link: "https://googleconquestio.com"}
],
pageInfo3: [
{title: "Applications"},
{text: "application item 1", link: "https://google.com"},
{text: "application item 2", link: "https://googleconquestio.com"}
]
}
A couple things are happening. First you are not returning the newly created array that map returns. Second you will also need to loop through each of your keys in your navigation object since they are arrays. You are trying to grab {title, text} from object[property][i], but that won't work since title is at index 0 and text is at index 1. I would recommend re-structuring your data.
You could do something like this:
const navigation = [
{
title: 'Title 1',
text: [
{
name: 'item 1',
},
{
name: 'item 2',
}
],
},
{
title: 'Title 2',
text: [
{
name: 'item 1',
},
{
name: 'item 2',
}
],
}
];
return navigation.map(obj => {
let listElements = obj.text.map((li, c) => {
return (
<li key={c}>{li.name}</li>
);
});
return (
<ul>
{obj.title}
{listElements}
</ul>
);
});
You need to have a return in the arrow function if you use braces that way:
Here is an example JSBin: https://jsbin.com/mijuh/2/edit?js,console
getLinks = (object) => {
return Object.keys(object).map((property, i) => {
const { text, title } = object[property][i];
console.log(object[property][i])
return (
<ul>{title}
<li>{text}</li>
</ul>
)
});