add JSX element through state in ReactJS - reactjs

I'm making a chat log which will display userA and userB chat conversation.
My initial state:
var initialState = {
message: '', //my input message
receivedMessage: null //all old messages
}
My handling function when click send button:
handleSend = () => {
var message = () => {
return (<p className="my-text">{this.state.yourName + ": " + this.state.message}</p>);
};
var oldMessages = this.state.receivedMessage;
this.setState({receivedMessage: oldMessages + message, message: ''});
dataChannel.send(message); //WEBRTC data channel
}
My handling received message function:
receiveChannel.onmessage = (event) => {
var oldMessages = this.state.receivedMessage;
var userB = this.state.callToUser;
var message = () => {
return (<p className="receive-text">{userB}: event.data</p>);
}
this.setState({
receivedMessage: oldMessages + message
})
};
My JSX element which store the conversation:
<div className="panel-body text-left">{this.state.receivedMessage}</div>
But this didn't work, I don't get the display I want. Can anybody tell me where did I do wrong and give me a solution for this? Any help is appreciated!

Related

Reactjs updated prop is not shown

I tried to create a interactable map following this example here: https://docs.mapbox.com/mapbox-gl-js/example/cluster/
In my componentDidMount (where I create a mapboxgl) I implemented clickable markers, when clicked on the markers a popup appears which displays various informations.
After the click I want to call a second function (fetch) to get more data on that specific marker: this.props.getData(id);
I then want to display these data in the same popup as the other information.
My problem is that this.props.testdata is empty on the first click. If I double-click on the marker, the data appear. So my guess is that my component does not notice the change of the state/prop and therefore does not update?
How do I do that or what am I missing?
Map.js
this.map.on('click', 'unclustered-point', (e) => {
const coordinates = e.features[0].geometry.coordinates.slice();
const id = e.features[0].properties.id;
const infos = e.features[0].properties.infos;
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
if (id == null) {
console.log("Missing id, cant get informations")
return;
}
this.props.getData(id);
new mapboxgl.Popup()
.setLngLat(coordinates)
.setHTML(
`
Id: ${id}
<br>
Infos: ${infos}
<br>
<br>
Testdata: ${this.props.testdata}
`
)
.addTo(this.map);
});
this.map.on('mouseenter', 'clusters', () => {
this.map.getCanvas().style.cursor = 'pointer';
});
this.map.on('mouseleave', 'clusters', () => {
this.map.getCanvas().style.cursor = '';
});
});
App.js (getData function):
getData = (id) => {
if (id== null) {
console.log("Missing id")
return;
}
const {mapCenter, startDate, endDate} = this.state;
const neo4j = require('neo4j-driver')
const driver = neo4j.driver('bolt://xxx', neo4j.auth.basic("xx", "xx-xx"))
const session = driver.session()
session
.run('Here goes a neo4j cypher statment',{id: id})
.then((results)=> {
const data= [];
results.records.forEach((record) => data.push([record.get("r"), record.get("n"), record.get("b")]))
this.setState({
data
});
session.close()
driver.close()
}).catch(e => {
console.log(e)
session.close();
});
};
I am not familiar with neo4j, but it is apparent that getData(id) fetches data from a server. This is going to be an asynchronous operation, so you should add a state property to maybe show a spinner while data is being fetched?
Regarding testdata not being available, I do not see the code where it is being set.
Maybe your setState code should be:
this.setState({
testdata: data
});
//If your data prop is testdata.
As per the current setState, data property of your component state would be set with server response.
Updates:
Temporary fix for async server call:
You can change following methods and try if it fixes your issue:
this.map.on('click', 'unclustered-point', async (e) => {
// ...previous code
await this.props.getData(id);
// This forces the following code to execute synchronously. Basically it should wait for your API call to be complete
new mapboxgl.Popup()
.setLngLat(coordinates)
.setHTML(
`
Id: ${id}
<br>
Infos: ${infos}
<br>
<br>
Testdata: ${this.props.testdata}
`
)
.addTo(this.map);
});
this.map.on('mouseenter', 'clusters', () => {
this.map.getCanvas().style.cursor = 'pointer';
});
this.map.on('mouseleave', 'clusters', () => {
this.map.getCanvas().style.cursor = '';
});
});
getData = (id) => {
//... previous code
// we return a promise to use await in the onClick handler
return session
.run('Here goes a neo4j cypher statment',{id: id})
.then((results)=> {
const data= [];
results.records.forEach((record) => data.push([record.get("r"), record.get("n"), record.get("b")]))
this.setState({
data
});
session.close()
driver.close()
}).catch(e => {
console.log(e)
session.close();
});
}
If you are still facing an issue, please create a sample app and share.
I have not yet managed to fix the original problem.
However, I have found another solution:
In my Map.js I'm calling the this.props.testdata in th UI like this:
<div className="sidebar">
info: {JSON.stringify(this.props.testdata)}
</div>

React/Socket.io - Client emits to all other clients only once and then only emits to itself after that

Running into an issue with React/Socket.io. I have two different socket emitters/listeners: one for a chat, and one for keeping track live changes to the application. I have two separate windows running localhost. The issue is when i emit a change on one window, the other window can receive that change the first time but never again (i.e. get first chat message but none that follow). After that first emit/receive, the sending client starts to receive its own emitters.
front end code:
`
socket = io("localhost:3002");
componentDidMount() {
//get id from url
const { id } = this.props.match.params;
//join specific room for project
this.socket.on("connect", () => {
this.socket.emit("room", this.projectId);
});
//listener for incoming messages
this.socket.on("RECEIVE_MESSAGE", (data) => {
this.props.addChat(this.projectId, data);
});
this.socket.on("UPDATE_PROJECT", () => {
console.log("update");
this.props.fetchProject(id);
});
}
emitTaskChange = () => {
this.socket.emit("TASK_CHANGE", { data: null });
};
onChatSubmit = (e) => {
e.preventDefault();
//create object with current user as author, message, and a timestamp
const chat = {
author: this.props.currentUser.name,
message: this.state.newChat,
createdAt: new Date().toLocaleString(),
};
//send message through socket
this.socket.emit("SEND_MESSAGE", chat);
//call action creator to add new chat
this.props.addChat(this.projectId, chat);
this.setState({ currentMessage: "" });
};
handleTaskEdit = (taskId, currentStatus) => {
const newStatus = currentStatus === "todo" ? "inprogress" : "completed";
this.props.editTask(this.projectId, taskId, newStatus);
this.emitTaskChange();
};
`
backend code:
`
const io = socket(server);
//create separate chat rooms using project id
io.on("connection", (socket) => {
socket.on("room", (room) => {
socket.join(room);
socket.in(room).on("SEND_MESSAGE", (message) => {
socket.emit("RECEIVE_MESSAGE", message);
});
socket.in(room).on("TASK_CHANGE", (data) => {
socket.emit("UPDATE_PROJECT", data);
});
});
`
found the error:
had to change the server-side code from socket.on and instead use the io object that was initialized such as io.sockets.on

Not able to add chat message using Sockjs in react native

I am facing issue in adding chat message in my Flatlist because I am not able to call any function inside stompClient.subscribe ()
My code is as following :
dummy='dummyurl';
sock = new SockJS(this.dummy);
componentDidMount() {
var that = this;
this.sock.onConnect =(e) =>{
console.log("connected")
}
this.sock.onopen = function() {
console.log('open');
var dummy2='dummyurl';
var sock2 = new SockJS(dummy2);
let stompClient = Stomp.over(sock2);
stompClient.heartbeat.outgoing = 20000;
stompClient.heartbeat.incoming = 0;
stompClient.connect({}, (frame) => {
stompClient.subscribe('xyz/getChat', (messageOutput) =>{
var mymessage =JSON.parse(messageOutput.body).message;
this.state = {
incomingchatMessage: "",
chatMessages:[]
}
that.setState({incomingchatMessage:mymessage}) //getting issue setState not found
console.log(this.state)
});
});
};
this.sock.onmessage =(e) =>{
console.log('message', e);
alert("on message calledj")
};
this.sock.onmessage = evt => {
console.log("erve");
}
}
In this code I am able to get net message inside new_message variable but not able to update state value here .
Any solution of this condition .

Bot Framework Webchat links onclick in React

Because of other services that are integrated to the bot, we have to use HTML anchors instead of the markdown.
When there is a link, we dynamically switch it to the following code:
var newStr = sub.replace('*|', '<a class="chatbot-link" title="help" href="#" onClick={this.click}>').replace('*', '</a>');
The goal is when the link is clicked, I sends the text content back to the bot as a response. The issue is that I cannot figure out how to catch the onclick event. Only thing it does when click is that it generates a seperate index.js in the page sources.
The base of the code I am using is a github webchat sample: Link
The code added that is important for the example (in MinimizableWebChat.js):
const MinimizableWebChat = (activityID, children) => {
const store = useMemo(
() =>
createStore({}, ({ dispatch }) => next => action => {
console.log(action.type);
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'initConversation',
value: {
language: window.navigator.language
}
}
});
} else if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
if (action.payload.activity.from.role === 'bot') {
setNewMessage(true);
// action.payload.activity.text = action.payload.activity.text;
// action.payload.activity.text = ();
action.payload.activity.text = ParseLinks(action.payload.activity.text);
var atts = action.payload.activity.attachments;
if (atts){
atts.forEach(att => {
att.content.body.forEach(obj => {
obj.text = EmphasizeContent(obj.text);
})
});
}
}
}
return next(action);
}),
[]
);
const items = ["Hello World!", "My name is TJ.", "I am from Denver."];
var text = "asd";
// const click = () => {
// store.dispatch({
// type: 'WEB_CHAT/SET_SEND_BOX',
// payload: {
// text
// }
// });
// }
const ParseLinks = (text) => {
if(!text) return text;
text = String(text);
var a=[], i=-1;
// Search for *|, if found, find next * and substirng. Add html to each substring
while((i=text.indexOf("*|",i+1)) >= 0) {
var iA = text.indexOf("*", i+2);
var sub = text.substring(i,iA+1);
// var newStr = sub.replace('*|', '<a class="chatbot-link" title="help" href="#" onClick={this.click}>').replace('*', '</a>');
var newStr = sub.replace('*|', '<a class="chatbot-link" title="help" href="#" onClick={this.click}>').replace('*', '</a>');
text = text.replace(sub, newStr);
}
return text;
}
I tried catching it in the middleware store and directly in bot MinimizableWebChat.js and WebChat.js. I need somekind of hook to get the event from ReactWebChat in some way to interact with it in the middleware.
Fyi, pretty new to React, thanks for the help.

Firebase - Phone number verification

So I'm building a simple app and I want to have phone number auth. However, after following the instructions on the site, nothing seems to be firing.
// App.js
handleNext = () => {
verifyPhoneNumber(this.state.phoneNumber);
this.setState(prevState => ({
activeStep: prevState.activeStep + 1
}));
};
...
<Button
size="small"
onClick={this.handleNext}
disabled={activeStep === maxSteps - 1}
id={"verify-phone-number-button"}
>
Next
</Button>
//Controller.js
export const verifyPhoneNumber = (phoneNumber) => {
console.log(phoneNumber) // +14084445555
firebase.auth().useDeviceLanguage();
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('verify-phone-number-button', {
'size': 'invisible',
'callback': function (response) {
// reCAPTCHA solved, allow signInWithPhoneNumber.
console.log("reCAPTCHA solved")
var appVerifier = window.recaptchaVerifier;
firebaseApp.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
.then(function (confirmationResult) {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
window.confirmationResult = confirmationResult;
console.log("success")
}).catch(function (error) {
console.log(error)
// Error; SMS not sent
// ...
});
}
});
}
reCAPTCHA solved never gets printed meaning it never makes it there. However, it also isn't printing any error messages so I'm unsure of what is happening.
Thanks for your help!

Resources