I am working on an application on "React-native". I read many manuals, but I did not find a solution to my problem. I just need to display the data from the firebase in the Listview table, but the keys to it are in a parallel node. Here is an example of the structure:

firebase data structure

I need to make the first request to get the keys, and the next to get and display the data in the listview.

At the moment, everything looks like this:

enter image description here

should be so

enter image description here

I know that the data is requested by the componentDidMount () function and is called once. I have a complete stupor, I killed a few days and did not find a solution. Can someone tell you the right solution or help edit the code to get the desired result?

Here is my implementation, but I only get data from the "costumers" for it:

constructor(props) { super(props); var userId = firebase.auth().currentUser.uid; this.ref = firebase.database().ref('/customers/' + userId); const myDataSource = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2, }); this.state = { dataSource: myDataSource }; } readData(ref) { ref.on('value', (dataSnapshot) => { var tasks = []; dataSnapshot.forEach((child) => { tasks.push({ name: child.val(), _key: child.key }); }); this.setState({ dataSource: this.state.dataSource.cloneWithRows(tasks) }); }); 

}

 componentDidMount() { this.readData(this.ref); } renderRow(rowData){ return ( <TouchableHighlight onPress={()=>this.pressRow(rowData)} underlayColor = '#dddddd'> <View style ={styles.row}> <Image source={require('./test_image.png')} style={styles.deviceImage} /> <View style={styles.rightContainer}> <Text style={styles.name}>Name: {rowData.name}</Text> <Text style={styles.ip}>IP: {rowData.name}</Text> <Text style={styles.user}>User: {rowData.name}</Text> </View> </View> </TouchableHighlight> ) } render() { return ( <View style={styles.backgroundMainScreen}> <Image style={styles.header} source={require('./test_avatar.png')} blurRadius={10}> </Image> <Image style={styles.avatar} source={require('./test_avatar.png')}> </Image> <View style={styles.listView}> <Text style={styles.nameUser}>Bill West</Text> <Text style={styles.street}>187 west street</Text> <Text style={styles.city}>New York, NY 10003</Text> <Text style={styles.bottomText}>last sync</Text> <ListView dataSource = {this.state.dataSource} renderRow = {this.renderRow.bind(this)}> </ListView> </View> </View> ) 

}

1 answer 1

I would wrap your requests in a separate component. Two requests are necessary - one for the user, one for his computers. I wrote the first one, the second one can be repeated by analogy. Although I suspect that a) there is a firebase hoc library on the githaba (I have to search, I think I saw it) b) it is possible to denormalize your data in the database and put the user's computers into the user object directly, without references.

I did not test the code, but I think the idea is clear

 import * as React from 'react'; interface Customer { CustomerName: string, computers: string[], } type CustomerQueryProps = { customerId: string, } type CustomerQueryState = { loading: boolean, error: boolean, customer: Customer } class CustomerQuery extends React.Component<CustomerQueryProps, CustomerQueryState> { state = { loading: true, error: false, } componentDidMount() { firebase.database().ref(`/customers/${this.props.customerId}`) .on('value', value => this.setState({ customer: value, loading: false, })) .on('error', err => this.setState({error: true, loading: false})); } render() { if (this.state.loading) return "Loading..."; if (this.state.error) return "Error!"; return this.props.children(this.state.customer); } } const App = () => { const userId = firebase.auth().currentUser.uid; return ( <CustomerQuery customerId={userId}> {customerData => ( <div> <h1>{customer.ComputerName}</h1> <CustomerComputers customerId={userId}> {computers => ( <div> {computers.map(computer => computer.name)} </div> )} </CustomerComputers> </div> )} </CustomerQuery> ) } 

Denormalization of DB:

enter image description here

  • I hope it helped - Daniel Khoroshko
  • Regarding your comment: b) it is possible to denormalize your data in the database, and place the user's computers into the user object directly, without references. Access to computers is only available from an authorized user. Just take all the computer and from the bottom to get the necessary will not work. If I understand you correctly - Sasha Tsvigun
  • I updated the answer above, in the picture you can see what kind of structure I had in mind. this way you can get everything in one request. On the other hand, it may not satisfy other tasks I don’t know about - Daniel Khoroshko
  • From your example, I realized that you need to create a separate JS file and put this code into it. And from my Computers file, call the Customer component and take properties from it, the CustomerName string and the computers array? - Sasha Tsvigun
  • I did not quite understand that there is a Customer component .. In general, I proposed the following solution: for each individual request you make, you can create a component request, for example CustomerQuery, as in my example. This component receives all the parameters necessary for making a request (for our example, this is customerId), makes a request, and when the request is completed, it calls the child function, which receives the result of the request at the input, and jsx at the output. This approach calls render props seems to be - Daniel Khoroshko