How to show only one specific user and not all in Firebase? - reactjs

I'm building a chat app using React Native and Firebase, All code is fine, but I want to show only one user in the list.
How to show only one specific user and not all?
For example:
Peter
John
Michael
Antony
Administrator
I want show Administrator, not all users.
state = {
users:[] }
componentWillMount(){
let dbRef = firebase.database().ref('users');
dbRef.on('child_added', (val) => {
let person = val.val();
person.phone = val.key;
if(person.phone===User.phone){
User.name = person.name
} else {
this.setState((prevState) => {
return {
users: [...prevState.users, person]
}
})
}
}) }
renderRow = ({item}) => {
return (
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Chat', item)}
style={{padding:10, fontSize: 16, color:'#00F0C8', borderBottomColor: '#ccc', borderBottomWidth:1}}>
<Text style={{fontSize:20}}>{item.name}</Text>
</TouchableOpacity>
) }
render(){
return(
<SafeAreaView>
<Text>These are the Users list</Text>
<Card style={styles.maincard}>
<FlatList
data={this.state.users}
renderItem={this.renderRow}
keyExtractor={(item) => item.phone}
/>
</Card>
</SafeAreaView>
)}

Well, you can try to filter the list,
render(){
return(
<SafeAreaView>
<Text>These are the Users list</Text>
<Card style={styles.maincard}>
<FlatList
data={this.state.users.filter(elem => elem.name === "Administrator")}
renderItem={this.renderRow}
keyExtractor={(item) => item.phone}
/>
</Card></SafeAreaView>)}

Related

FlatList not rendering on list of text

New to react native. I have a simple component that takes in a list of ingredients and returns the items in a flatList of text. For some reason I can't get the data to render. Am I doing something wrong?
My ingredients looks like this:
const ingredients = [chicken, butter, oil]
const DisplayRec = ({ ingredients }) => {
return (
<View style={styles.container}>
<Text>Your Recipes</Text>
<FlatList
//keyExtractor={(recName) => recName}
data={ingredients}
renderItem={({ recName }) => (
<Text>{recName}</Text>
)}
/>
</View>
);
};
You are using it in incorrect manner
please try
<FlatList
//keyExtractor={(recName) => recName}
data={ingredients}
renderItem={({item, index}) => (
<Text>{item}</Text>
)}
/>
also please go throught the documentation of FlatList
https://reactnative.dev/docs/flatlist#required-renderitem
First you have to go through with the official documentation of
React-native .
flatlist documentation
you can just simply pass ingredients data to flatlist and render its
function
For live editing expo link
const ingredients = [
{
id: 'bd7',
title: 'chicken',
},
{
id: '3ac',
title: 'butter',
},
{
id: '5869',
title: 'oil',
},
];
export default function App() {
const renderItem = ({ item }) => (
<Text>{item.title}</Text>
);
return (
<View >
<FlatList
data={ingredients}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
);
}
you need to use return in render item
<FlatList
//keyExtractor={(recName) => recName}
data={ingredients}
renderItem={({ recName }) => {
return (
<Text>{recName}</Text>
)}}
/>
Hope it's working fine for you

Calling function of class based component from another component in react native

I have two components one is Messages and other component is Navigation it's a stack navigator component. I would like to call function named onRefresh of Messages component from component Navigation header buttons. Please see my code how can I achieve this.
Messages.js (component file)
export default class Messages extends Component {
// Constructor
constructor(props) {
super(props)
this.state = {
messages: [],
isLoading: true
};
}
// End Constructor
// Getting Messages from server
async getMessages() {
try {
const response = await fetch('https://reactnative.dev/movies.json');
const json = await response.json();
this.setState({ messages: json.movies });
} catch (error) {
console.log(error);
} finally {
this.setState({ isLoading: false });
}
}
// End Getting messages from server
componentDidMount() {
this.getMessages();
}
// On refresh the messages
onRefresh = async () => {
this.setState({isLoading: true,}, () => {this.getMessages();});
}
// Send now sms using button.
sendNowMessage = async (title) => {
Alert.alert(title, "asdasdas");
}
render() {
const { messages, isLoading } = this.state;
return (
<SafeAreaView style={styles.container}>
{isLoading ? <ActivityIndicator size="large" color="#0000ff" style={ styles.horizontal } /> : (
<FlatList
data={ messages }
keyExtractor={({ id }, index) => id}
onRefresh={() => this.onRefresh()}
refreshing={this.state.isLoading}
renderItem={({ item }) => (
<View style={styles.item}>
<Text style={{ marginBottom: 12, }}>{item.title}, {item.releaseYear}</Text>
<Button
onPress={() => this.sendNowMessage(item.title)}
title="Send SMS"
style={styles.sendSMS}
color="#841584"
accessibilityLabel="Learn more about this purple button"
/>
</View>
)}
/>
)}
</SafeAreaView>
);
}
}
Navigation.js (component file)
const Stack = createStackNavigator();
export default function Navigation() {
return (
<Stack.Navigator>
<Stack.Screen
name="AuthScreen"
component={AuthScreen}
options={{
title: "Welcome",
}}
/>
<Stack.Screen
name="Messages"
component={Messages}
options={{
headerTitle: 'Messages',
headerRight: () => {
return (
<View style={styles.headerButtons}>
<View style={{ marginRight:10, }}>
<TouchableOpacity
onPress={() => {
new Messages().onRefresh() <---- I am calling it like this.
}}
>
<Text
style={styles.actionButtons}
>
<Ionicons name="reload-sharp" size={20} color="black" />
</Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity
onPress={() => {
alert("working")
}}
>
<Text
style={styles.actionButtons}
>
<Ionicons name="filter" size={20} color="black" />
</Text>
</TouchableOpacity>
</View>
</View>
)
}
}}
/>
</Stack.Navigator>
);
}
I am calling onRefresh function like this new Messages().onRefresh() and getting the following error.
Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the Messages component.
I want to learn what is the best way to call onRefresh function.

React native looping through array

I have array of colors that is being rendered with a flatlist. The flatlist data is coming from remote url. The colors are hardcoded in the app. The issue is that I am having is that the json data that is coming from api contain more rows of data than the colors I have in a array which result in only 5 items showing. Can someone help me with allowing the colors to repeat (make the index of colors repeat over and over)
componentDidMount() {
fetch('https://reactnative.dev/movies.json')
.then((response) => response.json())
.then((json) => {
this.setState({data: json.movies});
})
.catch((error) => console.error(error))
.finally(() => {
this.setState({isLoading: false});
});
}
render() {
const Colors = ['#1abc9c', '#9b59b6', '#7b59f9'];
const {data, isLoading} = this.state;
return (
<SafeAreaView style={{flex: 1, padding: 24}}>
{isLoading ? (
<ActivityIndicator />
) : (
<FlatGrid
itemDimension={130}
data={data}
style={styles.gridView}
keyExtractor={({id}, index) => id}
// staticDimension={300}
// fixed
spacing={10}
renderItem={({item, index}) => (
<View
style={[
styles.itemContainer,
{backgroundColor: Colors[index]},
]}>
<Text style={{color: 'white'}}>{item.title}</Text>
<Text style={{color: 'white'}}>{item.releaseYear}</Text>
</View>
)}
/>
)}
</SafeAreaView>
Simply use a modulo: {backgroundColor: Colors[index % Colors.length]}
const Colors = ["#1abc9c", "#9b59b6", "#7b59f9"];
for (let i = 0; i < 10; i++) {
console.log(Colors[i % Colors.length]);
}

Get Key of nested Array from Flatlist

I have a flatlist that is receiving a friendsArray with the following data structure...
I have a modal that has an onPress function, with that onPress i'd like to get the value of this key. I have the following Code, but usually this code provides me with the key of whatever i just selected in the flatlist... i'd like to get the key of the item selected one level deeper, how do i do this?
Here is App.js
onFriendChatPress = key => {
let friend = this.state.friendsArray.find(game => { return game.key === key })
}
render(){
return{
<View>
<FriendsModal
onChatPress={() => this.onChatPress()}
onClosePress={() => this.closeModal()}
onFriendPress={() => this.onFriendPress()}
onFriendChatPress={() => this.onFriendChatPress()}
selGame={this.state.selGame}
visible={this.state.modalVisible}
selGame={this.state.selGame}
/>
</View>
}
Here is FlatList in the FriendsModal
<FlatList
style={styles.flatList}
data={this.props.selGame.friends}
horizontal={true}
renderItem={(info) => (
<ModalProfileCard
displayName={info.item.displayName}
image={info.item.image}
onFriendPress={() => this.props.onFriendPress(info.item.key)}
onFriendChatPress={() => this.props.onFriendChatPress(info.item.key)}
/>
)
}
/>
Here is the Card in the modal
function modalProfileCard(props) {
return (
<View style={styles.container}>
<TouchableOpacity onPress={props.onFriendsPress} style={styles.friendInfo}>
<Image style={styles.profImage} source={{ uri: props.image }} />
<View style={styles.nameContainer}>
<Text style={styles.name}>{props.displayName}</Text>
</View>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={props.onFriendChatPress}>
{buttonText}
</TouchableOpacity>
</View >
)
}
You can do something like this.
const onPress = (key) => {
//you have the key here
}
return (
<Flatlist
data={your_data}
renderItem={({item})=> <YourComponent {...item} onPress={onPress} />}
/> )
const YourComponent = ({key,onPress}) => {
const onPress = () => {
onPress(key);
}
return (
<TouchableOpacity onPress={onPress}>
</TouchableOpacity>
)
}
Though I understand is
In renderItem, shouldn't you use info.displayName instead of info.item.displayNam? and so on ..
There is also a parent FlatList? You are saving the selected game in state as selGame right? You can save it's index also and can pass to child component so It would be easy to find the selected game's key.

Access state in container component

How can I access (get and set) state inside a container component?
I am getting Undefined is not an object evaluating this.state.* because it cannot be accessed from MultiImagePost. Is there a way to bind this to the container component?
export default class ImagePost extends React.Component {
state = {
index: 0,
modalVisible: false,
currentImages: []
};
render() {
const { imageCount } = this.props;
if (imageCount == 1) {
return <SingleImagePost postObject={this.props} />
} else {
return <MultiImagePost postObject={this.props} />
}
}
const MultiImagePost = ({ postObject }) => (
<View>
<FlatList
data={[{key: 'a'}]}
renderItem={({item}) =>
<TouchableOpacity>
<View>
<FlatGrid
itemDimension={100}
items={postObject.images}
renderItem={({ item, index }) => (
<TouchableHighlight
onPress={() => {
this.setState({
modalVisible: true,
index: this.state.index,
currentImages: postObject.images
});
}}>
<Image
source={{ uri: item }}
/>
</TouchableHighlight>
)}
/>
</View>
</TouchableOpacity>
}
/>
</View>
);
}
MultiImagePost is a stateless(functional) component, so it has no state.
U should manage state in ImagePost or consider using React hook.
I can't run your code, if MultiImagePost is inside ImagePost, you may try to see if it works.
I think you have mixed up class component with functional component. You need to change your code a bit like,
export default class ImagePost extends React.Component {
state = {
index: 0,
modalVisible: false,
currentImages: []
};
render() {
const { imageCount } = this.props;
if (imageCount == 1) {
return <SingleImagePost postObject={this.props} />
} else {
return <>{this.MultiImagePost(this.props)}</> //Instead of component make it as function call
}
}
//Make this as instance function
MultiImagePost = (postObject) => (
<View>
<FlatList
data={[{key: 'a'}]}
renderItem={({item}) =>
<TouchableOpacity>
<View>
<FlatGrid
itemDimension={100}
items={postObject.images}
renderItem={({ item, index }) => (
<TouchableHighlight
onPress={() => {
this.setState({
modalVisible: true,
index: this.state.index,
currentImages: postObject.images
});
}}>
<Image source={{ uri: item }} />
</TouchableHighlight>
)}
/>
</View>
</TouchableOpacity>
}
/>
</View>
);
}

Resources