I tried to create a chat in my application. Messages are stored in a server and I comunicate with it with an API. I tried to make it real time chat so I used componentDidUpdate shouldComponentUpdate method (componentDidUpdate and componentwillupdate too) but there is a warning that appears telling me that make my application very weak... in any case I can't do it like this.
I want suggestions to be able to display the message when the user click on the send button and how can I have a notification of receipt of new messages
in case your server is not sending notifications on new message, you can implement polling mechanism to check server for any new message after certain small time intervals.
as long as you are fetching new messages and populating them, using redux, you will only need componentwillreceiveprops method which you can use to set state of new message array.
The warning is probably coming from the "unsafe" (deprecated in React 17) method componentwillupdate. These methods (including componentwillreceiveprops as Firdous mentioned) shouldn't be used anymore in preference for methods such as componentdidupdate.
What you're looking to achieve can be done with an appropriate use of componentdidupdate and perhaps getderivedstatefromprops if needed. For instance, if you have connected your chat view (and your message text input) to redux (which should hold the messages) the componentdidupdate method will listen to incoming prop changes (from the onPress event for instance from your text input) and can therefore update the view with the new props (messages).
I provide some code to more details:
componentDidUpdate(prevProps, prevState) {
if (prevState.msg !== this.state.msg) {
this.getMsgFromApi(this.state.userId).then(data => {
this.setState({ msg: data})
});
}
};
and to display messages when component will mount i do this:
componentWillMount() {
AsyncStorage.getItem(USERID_STORED)
.then(userIdStore => {
this.setState({ userId: userIdStore});
this.getMsgFromApi(this.state.userId).then(data => {
this.setState({ msg: data})
});
});
};
all message are dislaied in a flatlist
<View style={Styles.messagesContainer}>
<FlatList
style={Styles.flatlist}
data={this.state.msg.Conversation}
keyExtractor={(item) => item.datetime.toString()}
renderItem={({item}) => <MsgR msg={item}/>}
inverted= {-1}
/>
</View>
and I do a condition to differentiate if it is a user message or a received message because the API that handles the messages puts them like this :
"Conversation": [
{
"adherent": "received message",
"user": null,
"datetime":"2019-07-09
09: 42: 55"
},
{
"adherent":null,
"user":"user message",
"datetime":"2019-07-04 06: 14: 18"
}
2","user":null,"datetime":"2019-07-03 12: 34: 10"
},
]
display of messages according to the sender:
const msg = this.props.msg;
return (
<View style={[Styles.container, msg.user===null ? Styles.right : Styles.left]}>
<Text style={msg.user===null ? Styles.textMsgRight : Styles.textMsgLeft}>{msg.user===null ? msg.adherent : msg.user}</Text>
</View>
);
I found the solution by adding extraData flatlist prop:
<FlatList
style={Styles.flatlist}
data={this.state.msg.Conversation}
keyExtractor={(item) => item.datetime.toString()}
extraData={this.state} //this prop
renderItem={({item}) => <MsgR msg={item}/>}
inverted= {-1}
/>
and when I click the send button, I re-call getMsgFromApi() method:
onPressSend() {
AsyncStorage.getItem(USERID_STORED)
.then(userIdStore => {
this.setState({ userId: userIdStore});
this.sendMsgS(this.state.userId).then(() => {
this.setState({msgS: ''});
this method --> this.getMsgFromApi(this.state.userId).then(data => {
this.setState({ msg: data,});
});
});
});
}
and it's work fine: when I click on send button, I have the message sent displayed after a few ms, it's unpleasant but it works !
Related
I have a FlatList that fetches data from my API, and I want to refresh it everytime my database gets updated. Can someone help me?
My code:
export default class Feed extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: []
};
}
componentDidMount() {
fetch('http://192.168.200.100:3000/posts')
.then(response => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson
})
})
.catch(error => console.log(error))
}
render() {
return (
<KeyboardAvoidingView >
<Header>
<FeedModal></FeedModal>
</Header>
<FlatList
keyExtractor={props => props.id}
data={this.state.dataSource}
renderItem={({ item }) => <FeedPosts title={`${item.title}`} photoDesc={`${item.description}`} postImg={`${item.photo}`} ></FeedPosts>}
>
</FlatList>
</KeyboardAvoidingView>
);
}
}
To update the values inside your app when changes happen on it from the backend you will need either a Real Time database or you will have to work with web sockets:
Web Sockets:
WebSocket is an internet communication protocol with a relevant interesting feature: it provides a full-duplex channel over a single TCP connection.
With WebSockets, a client and a server are able to talk to each other in real time, like they're involved in a telephone call: once connected, the client is able to receive data from the server, without any need to continuously refresh the web page. On the other hand the server will also be able to receive data in real time from the client inside the same connection. for react native check this article about websockets ,it should be handled from backend too.
Realtime Database:
Real-time database contains the data which is been processing in real-time. It uses the real-time processing techniques to handle the workloads.
for example firebase realtime-database.
I'am doing the last modification on my react native application.
Well, the problem that I get is that when I enter my informations to connect, I'm showin a small boxDialog to say that the verification of your data is working (this time is for comparing information that user entered and sql server data) so when it's correct I'm accessing to home page.
My problem is sometimes, the internet isn't that good so I need that when verification take longer time to show an error saying "please verify your internet connection"
I don't know if there is a method or specific function!!
constructor(props){
super(props);
this.state={
isModalVisible:false,
}}
openModal = () =>{
this.setState({
isModalVisible:true
}) }
userRegister = () =>{
this.openModal();
fetch('http://192.168.1.7:80/recup.php',{
method:'post',
header:{
'Accept':'application/json',
'Content-type' :'application/json'
},
body:JSON.stringify({email:usermail,password:password,})})
.then((responseData)=>responseData.text())
.then((responseJson)=>{
if(responseJson =='Data Matched'){
this.props.navigation.navigate( 'Welcome')}
else{
alert("Merci de saisir vos données correctement")}
})
.catch((error)=>{console.error(error);})
}
render() {
if(!this.state.isLoading){
return(
....
<TouchableOpacity style={styles.butt} onPress={this.userRegister}>
<Text>Connection</Text</TouchableOpacity>
....
If you want to access this (I mean if you want to fetch) url http://192.168.1.7:80/recup.php you should have proper internet connection.
You can handle this with this react-native-netinfo library. https://github.com/react-native-community/react-native-netinfo
If 2 user is using the app, messages are being displayed on the left side of the screen. cannot differentiate between them (sender who sent what messages),It occurs only when use our own REST Api Call to onload,
But when send one new message at that time message will display separately sender and receiver format and one more scenario when i use twillio default getMessages method at that time also error won’t occur.
Twilio method to get Previous Messages on both user:
this.channel.getMessages(0).then((messages) => {
console.log("getMessages" + messages);
this.handleBatch(messages);
});
Please find screenshot above for your reference.Any one know how to fix this issue or any suggestions are welcome.
try adding the user who is writting to the giftedChat:
<GiftedChat
isAnimated
messages={this.props.messages}
onSend={messages => this.onSend(messages)}
user={{
_id: 'sarathy',
name: 'Minecraft',
}}
/>
Every message that has the user's _id: 'sarathy' will be displayed on the right.
example of message that will be displayed on the right side:
{
_id: 3,
text: 'How r u?',
createdAt: new Date(),
user: {
_id: 'sarathy',
name: 'React Native'
},
},
react-native-gifted-chat differentiates messages using user props, which specify
User sending the messages,
so you have to give user props as
<GiftedChat
messages={this.state.messages}
onSend={this.handleNewMessage.bind(this)}
user={{
_id: your user id
name: users name,
avatar: users image
}}
/>
name and avatar is useful for displaying name or image in gifted chat if you want
and onSend event send this user with text to twillio as
handleNewMessage = (message = {}) => {
this.channel.sendMessage( message[0].text, message[0].user)
.catch(error => console.error(error));
}
Now on your getMessages
this.channel.getMessages(0).then((messages) => {
console.log("getMessages" + messages);
this.handleBatch(messages);
});
before appanding gifted chat change message format as gifted chat want
only for example i m using state to set message
handleBatch= (message) => {
const messageData = this.formatMessage(message);
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, messageData),
}));
}
formatMessage(message) {
return {
_id: message.sid, // or your own unique id
text: message.body,
user: message.attributes, // here you can get your user parameters in message attributes which we send to identify user
createdAt: message.timestamp,
};
}
// change above conditions as you get response by twillio.
i hope it will help you.
if any query let me know.
anyone having this issue Like me not looking to docs code properly... Do one thing ... add _id in-place id... both message object in user props inside
I am using React native Webview to load my web app. I am posting message from my web app using window.postMessage and I have implemented onMessage callback
render(){
return <View>
<Text>{this.state.messageFromWebview}</Text>
<WebView onMessage={this.onWebViewMessage} source={{uri: webAppUri}} />
</View>;
}
In onWebViewMessage function, in doing
onWebViewMessage=(event)=>{
this.setState({
messageFromWebview: event.nativeEvent.data
})
}
Above code is going into infinite loop. While setting state, Webview rerendering and calling the post message that triggering the setState.
Is there any alternative or am I missing anything here. Is it possible to set the <Text/> to the message from the webview without rerendering the Webview.
I think the infinite loop is because of calling the event without const request. All you need to do is add const variable before setState. The following code works for me.
onWebViewMessage = (event) => {
// set const data
const WishData = event.nativeEvent.data;
// then excuting setState the constant data here
this.setState({
messageFromWebview: WishData
});
}
So I've run into an weird issue, maybe I'm doing something wrong here but I haven't had this problem before and my app is full of similar code.
Basically I'm trying to do a simple Firestore get() in a function attached to a button onPress. For some reason the code is not run, or if it is I'm not getting any feedback. If I put the same code in componentDidMount it runs and gives me the database snapshot.
Here are the two bits of code in question.
updated for the current binding I am using
this.usersRef = firebase.firestore().collection('users');
componentDidMount() {
this.usersRef
.get()
.then((snapshot) => {
console.log('TEST didMount snapshot', snapshot);
}).catch((error) => {
console.log(error)
});
}
submitSearch() {
console.log('submitSearch')
this.usersRef
.get()
.then((snapshot) => {
console.log('TEST submitSearch snapshot', snapshot);
}).catch((error) => {
console.log(error)
});
}
The submitSearch is called from here
<Button style={{marginTop: 3, marginBottom: 8}} primary onPress={() => this.submitSearch()}>
{strings.search}
</Button>
So I've tried a lot of things here and I can't seem to figure out why the code won't work in the submitSearch function. The only thing I see from that function is the console log saying submit search.
Any ideas would be appreciated! Thanks.
The issue was the way the function was bound.
I originally had the following in the constructor:
this.submitSearch = this.submitSearch.bind(this)
and was calling it in the button component with
onPress={this.submitSearch}
I removed the constructor binding and used just the following in the button component:
onPress={() => this.submitSearch()}
I thought I had done that already! But I can confirm this fixes the issue. It's strange that there are no warnings or errors though, seems like a scenario where they would be helpful instead of just not running the code.