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.
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>
What I Want to Do:
I want to render a list of elements using .map, then sort by most recent on top. I've tried adding .sort and .filter before rendering the element, but it doesn't seem to be working. I've done some quick Google searches, but came across posts which don't seem relevant to what i'm trying to do. (or it's just me).
I want to sort by date, with the most recent on top.
Render Component:
import React from "react";
import TransactionEntry from "./TransactionEntry";
function Transactions({ transactionList }) {
return (
<div className="flex flex-col items-start justify-start w-full h-[520px] overflow-auto gap-3 no-scrollbar">
{transactionList.map((transaction) => {
return (
<TransactionEntry
id={transaction.id}
retailer={transaction.retailer}
category={transaction.category}
price={transaction.price}
dateAdded={transaction.dateAdded}
/>
);
})}
</div>
);
}
export default Transactions;
Data Structure:
[
{
"id": "ts001",
"category": "Category",
"retailer": "Retailer",
"price": 1.99,
"dateAdded": "04/02/01"
},
{
"id": "ts002",
"category": "Category",
"retailer": "Retailer",
"price": 13.99,
"dateAdded": "04/02/04"
},
{
"id": "ts003",
"category": "Category",
"retailer": "Retailer",
"price": 119.99,
"dateAdded": "04/02/09"
}
]
You can sort before mapping in this way
{transactionList.sort((a, b) => new Date(a.dateAdded) - new Date(b.dateAdded)).map((transaction) => {
return (
<TransactionEntry
id={transaction.id}
retailer={transaction.retailer}
category={transaction.category}
price={transaction.price}
dateAdded={transaction.dateAdded}
/>
);
})}
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);
}
})
I have Json in the below form
[{
"shortName": "e2e",
"displayName": "E2E",
"description": "This is demo managed product",
"vertical": "Finance"
},
{
"shortName": "sfdsgs",
"displayName": "fsaewgs",
"description": "anything",
"vertical": "Community"
},
{
"shortName": "fga",
"displayName": "xcdf",
"description": "agfsf",
"vertical": "Finance"
}]
I want to use this json to display the option items in an antd tree select based on Vertical.
I want the filter to look like this , The Antd tree select i am using is
<TreeSelect
placeholder="Filter here"
dropdownStyle={{ maxHeight: 400, overflow: "auto" }}
style={{ width: "100%" }}
treeData={data}
treeCheckable={true}
onChange={onChange}
treeIcon={true}
/>
I am using react hooks , could somebody help me to convert the above json to the format Tree select requires so the output could be as shown in the image.
I made the demo on CodeSandBox
first i created distinct data based on "vertical" values then with map function created children for selectTree data.
i hope this could help you :)
const ConvertToTreeNode = () => {
const distinctData = [...new Set(OriginalJson.map(x => x.vertical))];
return [{
title: "Vertical",
value: "0-0",
key: "0-0",
children: distinctData.map((x, index) => ({
value: `0-0-${index}`,
key: `0-0-${index}`,
title: x
}))
};
}];
Demo
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.