When I use map() to return the names of devices in my database, it only returns the first name.I am not very confident with JavaScript so this may be a simple issue.
Here's my database:
[{
"dwelling_id": 1,
"rooms": [{
"room_id": 1,
"room_name": "Living Room",
"devices": [{
"id": 1,
"device_name": "Google Home",
}]
},
{
"room_id": 2,
"room_name": "BedRoom",
"devices": [{
"id": 2,
"device_name": "Smart Bulb 1",
}]
}...
Here's the code to return both Google Home and Smart Bulb in separate Bootstrap Cards:
{props.house.map(house => {
return (
<React.Fragment>
<Card>
<Card.Body>
<Card.Title>
{house.rooms[0].devices[0].device_name}
</Card.Title>
</Card.Body>
</Card>
</React.Fragment>
)}
})}
If I do this:
// If I change this...
{house.rooms[0].devices[0].device_name}
// to...
{house.rooms[1].devices[0].device_name}
My code only returns just Smart Bulb.
Note that I want to return both Google Home and Smart Bulb in two separate Cards.
Any help would be greatly appreciated, thank you!
You need to do a second and third .map inside our first map in order to return both rooms:
{props.house.map(house => {
return (
<React.Fragment>
<Card>
<Card.Body>
{
house.rooms.map((room) => (
room.map((device) => (
<Card.Title>{device.device_name}</Card.Title>
)
)
}
</Card.Body>
</Card>
</React.Fragment>
)
}
})}
You have 2 levels in your array, when you do props.house.map, you only get the first level object: dwelling. If you want to list all the rooms of a dwelling, then you need to make a second map like this:
props.house.map(dwelling => {
dwelling.map(room => {
console.log(room.devices[0].device_name);
}
})
Related
I'm receiving data from api like this:
{
"isTrue": true,
"data1": {
"username": "user1",
"images": [
"image1.jpg",
"image2.jpg"
]
},
"data2": {
"location": "new york",
"age": "80"
}
}
and setting it in my state as details.
I want to display data in flatlist, so I do this:
<FlatList
data={state.details}
renderItem={({item}) => {
<Details item={item} />;
}}
></FlatList>
in my component I render data like:
export default Details = ({item}) => {
return item
? Object.values(item).map(value => {
<Text>{value.data1?.username}</Text>;
})
: null;
};
Why don't the items render?
Make sure u pass Array to flat list
like :
const DATA = [
{
id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba",
title: "First Item",
},
{
id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63",
title: "Second Item",
},
{
id: "58694a0f-3da1-471f-bd96-145571e29d72",
title: "Third Item",
},
];
flat list will do for loop for you, so u don't need to values(item).map you can do:
export default Details = ({item}) => {
return
<View>
<Text>{item.isTrue}</Text>
<Text>{item.data1.username}</Text>
</View>
};
change
renderItem={({item}) => {
<Details item={item} />;
}}
to
renderItem={({item}) => {
return <Details item={item} />;
}}
or
renderItem={({item}) => (<Details item={item} />)}
finally don't forget to add <View></View> as parent for <Text><Text>
I have this object that I'm trying to loop over in a form but really can't get it to work. Here is sample of the object.
const data = {
"Social Security": [
{
label: "Deduction Type",
value: "Social Security",
name: "SocialSecurity"
},
{
label: "Employer Rate",
value: "12.4%",
name: "SocialEmployer"
},
{
label: "Employee Rate",
value: "6.2%",
name: "SocialEmployee"
}
],
"Medicare": [
{
label: "Deduction Type",
value: "Medicare",
name: "Medicare"
},
{
label: "Employer Rate",
value: "1.45%",
name: "MedicareEmployer"
},
{
label: "Employee Rate",
value: "2.9%",
name: "MedicareEmployee"
}
]
}
form implementation
<Formik>
{({ values, isSubmitting, resetForm, setFieldValue }) => (
<Form id="payrollSettingsForm" >
<Grid container className={classes.border}>
<Grid item xs={12} md={4}>
{Object.entries(data).map(arr =>{
Array.isArray(arr) && arr.map(elm =>{
return (<TextField
label={elm.label}
value={elm.value}
name={elm.name}
/>)
})
})}
</Grid>
</Grid>
...rest of the form
</Form>
</Formik>
Tried many approaches like Object.fromEntries(). forEach I think all the methods I can find example and keep failing, maybe I'm doing something wrong, any help will be appreciated.
{Object.entries(data).map(([key, val]) =>{
return val.map(elm =>{
return (
<TextField
label={elm.label}
value={elm.value}
name={elm.name}
/>
)
})
})}
Map should return an element on each iteration. In case you don't want to display return null else return a react node.
<Grid item xs={12} md={4}>
{Object.entries(data).map(arr => {
Array.isArray(arr) ? arr.map(elm => {
return (<TextField
label={elm.label}
value={elm.value}
name={elm.name}
/>)
}) : null
})}
</Grid>
I have this JSON data in another file:
{
"feed": [
{
"id": 1,
"text": "Hey everyone I'm looking for help with my meditation, when does everyone do it?",
"messages": [
{
"id": 1,
"text": "I like to do it first thing in the morning and sometimes at night!",
},
{
"id": 2,
"text": "Thanks I'll try that!",
}
]
},
{
"id": 2,
"text": "Have you tried a weighted blanket?",
"messages": [
{
"id": 3,
"text": "Yeah, they're great, I have the 10lb one!",
},
{
"id": 4,
"text": "Thank you!",
}
]
}
]
}
I successfully rendered the two sets of data under "feed" using the map function by doing this:
<div>
{Data.feed.map(feed => {
return(
<>
<h4>{ feed.id }</h4>
<p>{ feed.text }</p>
</>
)})
}
</div>
My question is: how do I also render the inner messages loop? I was told to use a nested .map and here's what I unsuccessfully attempted:
<div>
{Data.feed.map(feed => {
return {feed.messages.map(messages => {
return (
<>
<h4>{ feed.id }</h4>
<p>{ feed.text }</p>
<h5>{ messages.id }</h5>
<p>{ messages.text }</p>
</>
)}
)}
})}
</div>
You were actually close. You currently loop over the feed array only. You need to use a second map() to iterate over the messages too inside every item of the feed.
Check out the snippet below:
function App() {
return (
<div>
{data.feed.map((feed) => (
<React.Fragment key={feed.id}>
<h4>{feed.id}</h4>
<p>{feed.text}</p>
<ul>
{feed.messages.map((message) => (
<li key={message.id}>{message.text}</li>
))}
</ul>
</React.Fragment>
))}
</div>
);
}
const data = {
feed: [
{
id: 1,
text:
"Hey everyone I'm looking for help with my meditation, when does everyone do it?",
messages: [
{
id: 1,
text:
'I like to do it first thing in the morning and sometimes at night!',
},
{
id: 2,
text: "Thanks I'll try that!",
},
],
},
{
id: 2,
text: 'Have you tried a weighted blanket?',
messages: [
{
id: 3,
text: "Yeah, they're great, I have the 10lb one!",
},
{
id: 4,
text: 'Thank you!',
},
],
},
],
};
ReactDOM.render(<App />, document.querySelector('#root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Currently I am struggling with iterating over an object containing an array with objects. (and nested ones) I am trying to create a generic Table Component in React so it can be used by many views.
What did I setup?
tableData.map((prop, key) => {
return (
<TableRow key={key}>
<TableCell className={classes.tableCell} key={key}>
{prop.number}
</TableCell>
<TableCell className={classes.tableCell} key={key}>
{prop.TableType.max_occupancy}
</TableCell>
<TableCell className={classes.tableCell} key={key}>
{prop.price}
</TableCell>
<TableCell className={classes.tableCell} key={key}>
{prop.TableType.description}
</TableCell>
<TableCell className={classes.tableCell} key={key}>
<Button fullWidth color="primary">
Remove
</Button>
</TableCell>
</TableRow>
);
})
The problem that I am facing right now?
I can not create the content above in a dynamic way. I am encountering several issues like for example:
The nested objects logic
The logic should not clash with other implementations in other pages. (react)
What would I like to achieve?
I would like to achieve something that is generic and can be used in a wide range of scenarios and does not clash with other pages where this component is being used.
In the end it should look something like this in a visual way:
What data do I have?
[
{
"id": 1,
"number": 1,
"status": true,
"price": 12,
"table_type_id": 1,
"venue_id": 1,
"TableType": {
"id": 1,
"description": "Small Table",
"max_occupancy": 3
}
},
{
"id": 2,
"number": 2,
"status": true,
"price": 2,
"table_type_id": 2,
"venue_id": 1,
"TableType": {
"id": 2,
"description": "Medium Table",
"max_occupancy": 6
}
}
]
The Codesandbox directory with the full project:
https://codesandbox.io/embed/lwzz4j9mz?autoresize=1&eslint=1
The fill we are talking about is located at the Components/Table/Table.jsx. (I have added some dummy data in the comments that needs to be parsed to Table rows and cells)
Properties that needs be used in the view:
number
price
id
TableType
Hopefully someone can come up with a smart idea to help me out with this issue! Cheers for all the help and hopefully we can fix this together.
You should probably use an external library to get this done. But if you want to go for an in house approach this would be one way to go about it.
To the component, send the data and the header.The header should also specify how the data should be parsed to receive it's value.
var defaultTemaplate = '<TableRow><TableCell style={{ textAlign: "center" }}>Woooops! You haven\'t applied any tables for this venue yet. To start renting out tables you should add at least 3 tables tothe app. Just press the button above to start imediately.</TableCell></TableRow>'
var tableHead = [{
title: 'number',
type: 'data',
path: 'number'
},
{
title: 'TableType',
type: 'data',
path: 'TableType.description'
},
{
title: 'Edit/delete',
type: 'template',
templateString: '<button></button>'
}
] //for all columns
var tableData = [{
"id": 1,
"number": 1,
"status": true,
"price": 12,
"table_type_id": 1,
"venue_id": 1,
"TableType": {
"id": 1,
"description": "Small Table",
"max_occupancy": 3
}
},
{
"id": 2,
"number": 2,
"status": true,
"price": 2,
"table_type_id": 2,
"venue_id": 1,
"TableType": {
"id": 2,
"description": "Medium Table",
"max_occupancy": 6
}
}
]
console.log(genRows(tableData))
function getTableCells(data) {
return tableHead.map((opts) => {
if (opts.type === 'data') {
return `<TableCell className={classes.tableCell}>${_.at(data, opts.path)}</TableCell>`
}
if (opts.type === 'template') {
return opts.templateString
}
})
}
function genRows(tableData) {
if (tableData.length < 0) return defaultTemaplate;
return tableData.map((rowData) => `<TableRow>${getTableCells(rowData)}</TableRow>`)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
This is just an example to demonstrate one approach you could take, not full fledged code and can defenetly be improved.
I've been trying to learn React Native but it has been tougher than I thought. I can't create a simple "master-detail" app (and I couldn't find a good, simple tutorial explaining how to do it either).
I've managed to display a list of categories. After clicking one, it should display the category name + the list of items from this:
const data = [{
"category": "Fruits",
"items": [{
"name": "Apple",
"icon": "apple.png"
}, {
"name": "Orange",
"icon": "orange.png"
}]
}, {
"category": "Vegetables",
"items": [{
"name": "Lettuce",
"icon": "lettuce.png"
}, {
"name": "Mustard",
"icon": "mustard.png"
}]
}];
On my main class, I managed to display a list of categories:
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) =>
<Text onPress={this.onPressItem.bind(this, rowData.category)}>
{rowData.category}
</Text>}
/>
In my onPressItem I have the following:
onPressItem(category) {
this.props.navigator.push({
name: 'DetailView',
component: DetailView,
passProps: {
category
}
});
}
In my detail view, the category name is not being displayed:
class DetailView extends Component {
render() {
return (
<View style={ styles.container }>
<Text>Category: { this.props.category }</Text>
<TouchableHighlight onPress={ () => this.props.navigator.pop() }>
<Text>GO Back</Text>
</TouchableHighlight>
</View>
);
}
}
I'd really appreciate if someone can help me with this. It's probably something silly I'm doing wrong. Creating this simple thing can't be that hard. :/
Full code
I found a solution. I was making a mistake when rendering the view:
return React.createElement(
route.component,
{ navigator },
{...route.passProps}
);
The right way is:
return React.createElement(
route.component,
{ navigator, ...route.passProps }
);
Thanks to mehcode for helping me out.