I'm using the liowebrtc react library to create a chat app. This library assigns a unique identifier (peer.id) to each peer (people not you in your chatroom). However, you can also assign yourself a nickname which then gets passed as peer.nick. At least, that's how it's supposed to work. But the peer.nick value always returns undefined, even though it's present in the Peer object. For instance, I pass a nickname to the Liowebrtc component as shown below:
<LioWebRTC
options={{ debug: true,
dataOnly: true,
nick: "Pippin" }}
onReady={join}
onCreatedPeer={handleCreatedPeer}
onReceivedPeerData={handlePeerData} >
If I print the peer object to console in handleCreatedPeer (the function that gets called when the app is informed of the presence of someone other than yourself in the chat room), I can see peer has a nick with value "Pippin." However, trying to call peer.nick or peer["nick"] always produces undefined.
For instance,
console.log("Peer id: ", peer.id); // valid value
console.log("Peer nick: ", peer.nick); // undefined
console.log("Peer one: ", peer.oneway); // valid value
even though if I print the Peer object in console, I can see:
Strangely though, I I print the keys of the Peer object in console, I see:
As you can see, nick is missing from the key list, even though it's there when you log the object in its entirety.
Why is peer.nick always undefined? Is there a different way I'm supposed to call it?
Here is the ChatWrapper class in its entirety:
// Code modified from https://medium.com/#leontosy/building-a-p2p-web-app-with-react-and-liowebrtc-6a7e8c621085
import React, { useState } from 'react';
import { LioWebRTC } from 'react-liowebrtc';
import ChatBox from './ChatBox';
const ChatWrapper = props => {
const [chatLog, setChatLog] = useState([])
const addChat = (name, message, alert = false) => {
setChatLog( chatLog => {
return [ ...chatLog,
{
name,
message: `${message}`,
timestamp: `${Date.now()}`,
alert
}
];
})
};
const join = (webrtc) => webrtc.joinRoom(props.roomID.toString());
const handleCreatedPeer = (webrtc, peer) => {
console.log(peer.nick)
addChat(`Peer-${peer.id.substring(0, 5)} joined the room!`, ' ', true);
}
const handlePeerData = (webrtc, type, payload, peer) => {
switch(type) {
case 'chat':
addChat(`Peer-${peer.id.substring(0, 5)}`, payload);
break;
default:
return;
};
}
return (
<div>
<p>Room: {props.roomID}</p>
<LioWebRTC
options={{ debug: true,
dataOnly: true,
nick: "Pippin"}}
onReady={join}
onCreatedPeer={handleCreatedPeer}
onReceivedPeerData={handlePeerData} >
<ChatBox
chatLog={chatLog}
onSend={(msg) => msg && addChat('Me', msg)}
/>
</LioWebRTC>
</div>
);
}
export default ChatWrapper;
and here is the ChatBox class in its entirety:
// Code from https://medium.com/#leontosy/building-a-p2p-web-app-with-react-and-liowebrtc-6a7e8c621085
import React, { Component } from 'react';
import './ChatBox.css';
import { withWebRTC } from 'react-liowebrtc';
class ChatBox extends Component {
constructor(props) {
super(props);
this.state = {
inputMsg: ''
};
}
generateChats = () => {
if(this.chatBox) {
setTimeout(() => { this.chatBox.scrollTop = this.chatBox.scrollHeight; }, 2);
}
return this.props.chatLog.map((item) => (
<div className="chat" key={`chat-${item.name}-${item.timestamp}`}>
<b className="name" style={{ color: item.alert ? '#888' : '#333' }}>{item.name}</b> <span className="msg">{item.message}</span>
</div>
));
}
handleSend = (chatMsg) => {
this.props.webrtc.shout('chat', chatMsg);
this.props.onSend(chatMsg);
}
handleKeyUp = (evt) => {
if (evt.keyCode === 13) {
this.handleSend(this.state.inputMsg);
this.setState({ inputMsg: '' });
}
}
handleInputChange = (evt) => this.setState({ inputMsg: evt.target.value });
render() {
const { chatLog } = this.props;
return (
<div className="container">
<div className="chatHeader">
<h1 className="title">P2P Chat Example</h1>
<hr />
</div>
<div className="chatBox" ref={(div) => this.chatBox = div}>
{chatLog.length ? this.generateChats() : (
<div className="info">
<p>To test this component out, open this page in a new tab or send it to a friend.</p>
</div>
)}
</div>
<hr />
<div className="bottomBar">
<input className="chatInput" type="text" placeholder="Type a message..." onKeyUp={this.handleKeyUp} onChange={this.handleInputChange} value={this.state.inputMsg} />
</div>
</div>
);
}
}
export default withWebRTC(ChatBox);
Please find my codebases below that are relevant to my question.
I am having trouble trying to develop a discard() function that would remove a card on the browser upon double-clicking the card you desire to discard. The commented-out discard function works correctly, but only discards the last card in your hand whereas I am trying to make it to where, with a user's double-clicking on a specific card, that card would be removed giving the user more liberty to choose the card he/she wishes to discard.
Any assistance, guidance, or reference material would be greatly appreciated!
Parent Component: PlayersHand.js
import React from 'react';
import './PlayersHand.css';
import { currentGameDeck, playerOneHand } from '../Logic/game_logic';
import PlayingCard from '../PlayingCard/PlayingCard';
class PlayersHand extends React.Component {
constructor(props) {
super(props)
this.state = {
cards: playerOneHand,
setOne: [],
setTwo: [],
setThree: []
}
this.draw = this.draw.bind(this);
//this.discard = this.discard.bind(this);
}
draw() {
let newCard = currentGameDeck.shift();
this.setState({ cards: [...this.state.cards, newCard] })
}
handleDiscard = id => {
let currentArray = [...this.state.cards]
console.log(currentArray)
let discardedCard = currentArray.findIndex(card => card.id === id);
if (discardedCard === -1) {
return
}
let newArray = currentArray.splice(discardedCard, 1);
this.setState({ cards: newArray })
}
/* discard() {
let currentArray = [...this.state.cards]
let discardedCard = currentArray.pop();
let newArray = currentArray.filter(card => {
return card !== discardedCard
})
this.setState({ cards: [...newArray] })
} */
render() {
let handOfCards = this.state.cards.map((card, i) =>
<PlayingCard
card={card}
key={'card_' + i}
handleDiscard={this.handleDiscard}
/>
)
console.log(this.state.cards);
return(
<>
<div className="handful-of-cards">
{handOfCards}
</div>
<h2>Your current hand of cards!</h2>
<div className="card-play-options">
<button
onClick={this.draw}
>
Draw Card
</button>
<button
onClick={this.discard}
>
Discard Card
</button>
</div>
<div className="sets-row">
<section className="first-set">
</section>
<section className="second-set">
</section>
<section className="third-set">
</section>
</div>
</>
)
}
}
export default PlayersHand;
Child Component: PlayingCard.js
import React from 'react';
import './PlayingCard.css';
class PlayingCard extends React.Component {
constructor(props) {
super(props);
this.handleDoubleClick.bind(this);
}
handleDoubleClick = () => {
console.log(`${this.props.card.id}`)
this.props.handleDiscard(`${this.props.card.id}`)
}
render() {
return(
<img
src={`./cards/${this.props.card.desc}.png`}
alt={`${this.props.card.suit} ${this.props.card.number}`}
number={this.props.card.number}
suit={this.props.card.suit}
value={this.props.card.value}
id={this.props.card.id}
className="card"
onDoubleClick={this.handleDoubleClick}
/>
)
}
}
export default PlayingCard;
I am building a shopping cart using MERN stack. The problem is that my images are not appearing, and on refresh the image appears only momentarily. it is showing me an icon that the image cannot be displayed. All my images are in the images folder inside src folder. Here is my code.
import React, { Component } from "react";
import "../css/styles.css";
import {
Button,
Modal,
ModalHeader,
ModalBody,
ModalFooter,
Form,
FormGroup,
Label,
Input
} from "reactstrap";
import axios from "axios";
import Cart from "./cart1.component";
export default class BookDetails extends Component {
constructor(props) {
super(props);
this.state = {
book: [],
modal: false,
cover: ""
};
}
componentDidMount() {
axios
.get("http://localhost:4000/books/" + this.props.match.params.id)
.then(response => {
this.setState({ book: response.data, cover: response.data.cover });
})
.catch(function(err) {
console.log(err);
});
}
toggle = () => {
this.setState({
modal: !this.state.modal
});
};
AddToCart = e => {
const { book } = this.state;
let id = book._id;
let cover = book.cover;
let price = book.price;
let qty = 1;
let product = { id: id, cover: cover, price: price, qty: qty };
let existing = JSON.parse(sessionStorage.getItem("cart"));
existing = existing ? existing : [];
let val = existing.filter(item => item.id === id);
if (existing.length !== 0) {
if (val.length != 0) {
existing.forEach(item => {
if (item.id === id) {
item.qty++;
}
});
} else {
existing.push(product);
}
} else {
existing.push(product);
}
sessionStorage.setItem("cart", JSON.stringify(existing));
};
getImages = cover => {
let imagesURL = [
"../images/csharp.jpg",
"../images/css.jpg",
"../images/javascript.jpg",
"../images/json.jpg",
"../images/lpthw.jpg",
"../images/mongodb.jpg",
"../images/node.jpg",
"../images/php.jpg",
"../images/python.jpg",
"../images/sql.jpg"
];
const bookUrl = `../images/${cover}`;
let coverUrl = "../images/nocover.jpg";
imagesURL.forEach(url => {
if (url == bookUrl) {
coverUrl = bookUrl;
}
});
return coverUrl;
};
render() {
const { book, quantity } = this.state;
let src = this.getImages(this.state.cover);
return (
<div className="container">
<div className="row">
<div className="col-sm-6">
<img src={src}></img>
</div>
<div className="col-sm-6">
<h2>{book.title}</h2>
<ul>
<li>Category: {book.category}</li>
<li>Author: {book.author}</li>
</ul>
<p className="button blue">${book.price}</p>
<p>{book.description}</p>
<button
id={book._id}
onClick={() => {
this.toggle();
this.AddToCart();
}}
className="btn btn-success"
>
Add to Cart
</button>
<Modal isOpen={this.state.modal} toggle={this.toggle}>
<ModalHeader toggle={this.toggle}>My Cart</ModalHeader>
<ModalBody>
<Cart></Cart>
</ModalBody>
</Modal>
</div>
</div>
</div>
);
}
}
I had been stuck on it for almost two days now. I tried using require in the src component but that is giving me an error that the ../images/nocover.jpg module cannot be found. Please, I would really appreciate some help.
I recently moved my workspace to Linux centOS from Windows10. When I run this code in Windows 10. It works and I am able to upload file to the server. But when I change the environment to CentOS. It still show the output but it does not send file to the server and show error "URI is malformed"
here are my codes
import React from 'react';
import axios from 'axios';
import Swal from 'sweetalert2';
import withReactContent from 'sweetalert2-react-content';
const MySwal = withReactContent(Swal);
const BASE_URL = 'http://localhost:5000';
class UploadPDF extends React.Component {
constructor(props)
{
super(props);
this.state =
{
images: [],
imageUrls: [],
message: ''
}
}
selectImages = (event) =>
{
let images = []
for (var i = 0; i < event.target.files.length; i++)
{
images[i] = event.target.files.item(i);
}
images = images.filter(image => image.name.match(/\.(pdf)$/))
let message = `${images.length} valid File(s) selected`
this.setState({ images, message })
}
uploadImages = () =>
{
MySwal.fire('File Uploaded','The File Is Uploaded!','success'
);
const uploaders = this.state.images.map(image =>
{
const data = new FormData();
data.append("image", image, image.name);
// Make an AJAX upload request using Axios
return axios.post(BASE_URL + 'upload', data)
.then(response =>
{
this.setState(
{
imageUrls: [ response.data.imageUrl, ...this.state.imageUrls ]
});
})
});
axios.all(uploaders).then(() =>
{
console.log('done');
}).catch(err => alert(err.message));
}
render() {
console.log("Header - Rendered");
return(
<div className="container">
<div className="py-5 text-center">
<div className="jumbotron">
<div className="container">
<h1>Upload File</h1>
<hr/>
<p className="lead">Only PDF</p>
<input className="form-control " type="file" onChange={this.selectImages} multiple />
<p className="text-info">{this.state.message}</p>
<button className="btn btn-primary" value="Submit" onClick={this.uploadImages}>Submit</button>
</div>
</div>
</div>
</div>
);
}
}
export default UploadPDF;
This is the code I am stuck and dunno what to do. any links or suggestion ?
It's hard to tell exactly what's going on but my guess is you're combining the string in BASE_URL with "upload" so you wind up trying to post to http://localhost:5000upload rather than http://localhost:5000/upload.
Try adding a trailing slash on BASE_URL and see if that fixes your problem.
This said, I'm not sure why the OS would make a difference.
I am confused with reactjs api json call back.
In my container>> i have an api response from this --> let broadcast = this.props.broadcastDetailsPageApiResponse;
I need to map the values to 'broadcastData' variable to print it in component page html.(fileds like 'channel','description','recordedUrl',
How can i do it?
The api response as follows.
broadcastdetailcontainer.jsx: place to map console.log("need to map");line no 34.
import React, {Component} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux';
import BroadcastDetailPage from '../components/broadcastList/broadcastDetailPage.jsx'
import * as detailPageActions from '../actions/detailPageActions.jsx'
class BroadcastDetailContainer extends Component {
constructor(props) {
super(props);
this.state = {broadcastData: {}};
this.updateBroadcastData = this.updateBroadcastData.bind(this);
}
componentDidMount() {
let broadcastId = this.props.params.broadcastId;
console.log("Broadcast Id in the componentDidMount: " + broadcastId);
this.updateBroadcastData(broadcastId);
}
updateBroadcastData(broadcastId) {
let broadcastData;
let broadcast = this.props.broadcastDetailsPageApiResponse;
// console.log("broadcast: " + JSON.stringify(broadcast));
if (broadcast != null) {
/////////////////////////////////////////////////////////////////
broadcastData = broadcast.channel;
broadcastData = broadcast.user;
console.log("need to map");
//console.log(broadcastData);
/////////////////////////////////////////////////////////////////
}
let content = this.props.homePageApiResponse.content;
if (content != null & broadcastData == null) {
console.log('entered when the home API');
for (let i = 0; i < content.length; i++) {
if (content[i].id == broadcastId) {
broadcastData = content[i];
break;
}
}
}
if (broadcastData == null) {
content = this.props.searchPageApiResponse.content;
if (content != null) {
console.log('entered when the search API');
for (let i = 0; i < content.length; i++) {
if (content[i].id == broadcastId) {
broadcastData = content[i];
console.log(broadcastData);
break;
}
}
}
}
if (broadcastData == null) {
this.props.actions.callDetailApi(broadcastId);
}
else{
this.setState({broadcastData: broadcastData});
}
}
componentWillReceiveProps(nextProps) {
let broadcastId = nextProps.params.broadcastId;
console.log('componentWillReceiveProps');
this.updateBroadcastData(broadcastId);
}
render() {
//console.log("rendered: "+JSON.stringify(this.props.broadcastDetailsPageApiResponse));
return (
<div>
{this.state.broadcastData &&
<BroadcastDetailPage
broadcastDetail={this.state.broadcastData}/>
}
</div>
)
}
}
const mapStateToProps = (state) => ({
homePageApiResponse: state.homePageApiResponse,
searchPageApiResponse: state.searchPageApiResponse,
broadcastDetailsPageApiResponse: state.detailPageApiResponse,
})
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(detailPageActions, dispatch)
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)
(BroadcastDetailContainer)
I need to display the map values in the following component page:
import React, {Component} from "React";
import {Row, Clearfix} from "react-bootstrap/lib";
import VideoPlayer from "./videoPlayer.jsx";
class BroadcastDetailPage extends Component {
render() {
let broadcastData = this.props.broadcastDetail;
return (
<Row>
<div className="popup-cont-container">
<VideoPlayer broadcastData={broadcastData}/>
<div className="video-info">
<div className="info-left">
<div className="main-tag">
# {broadcastData.channel}
</div>
<div className="datenTime">
On Date
</div>
<div className="datenTime"> Location
</div>
<div className="video-info-main"> </div>
<div className="at">#
{broadcastData.handle} </div>
</div>
<div className="info-right">
<span><img src="images/eyeico.png"/>
<a> </a> Live viewers
</span>
<span><img src="images/heart.png"/>
<a> </a> Likes
</span>
</div>
</div>
<Clearfix/>
</div>
</Row>
);
}
}
export default BroadcastDetailPage
{"id":4,"user":{"userId":1,"chatUserId":0,"handle":"satishkrypto","countryCode":"+971","phone":"569942359","picUrl":"https://ss-ap-southeast-1.amazonaws.com/production-speakerswire-images/user-profiles/male3x.png","userStat":{"id":1,"followers":4,"followings":5,"broadcastLikes":0,"broadcastViews":90},"name":"satish verma","existingUser":false,"userProfileImageType":"MALE","invitesLeft":4,"userPriviledge":"SW_BROADCASTER"},"description":"satish's Broadcast","streamId":"pub11489928734882","audio":false,"screenShotUrl":"https://ss-api-eb-dev.s3-ap-southeast-1.amazonaws.com/broadcast-images/pub11489928734882-1489928751454.jpg","recordedUrl":"https://production-ss-videos-red5pro.s3-ap-southeast-1.amazonaws.com/video/record/pub581489997130311.mp4","status":"RECORDED","type":"PUBLIC","locationEnabled":false,"commentsEnabled":true,"channel":{"channelId":14,"channel":"Productivity","color":"#4A148C","priority":986,"created":1489922543000,"updated":1489922543000,"broadcast":0,"liveBroadcast":0},"broadcastStat":{"id":4,"likes":0,"views":14,"viewers":5,"liveViewers":0},"latitude":0.0,"longitude":0.0,"startTime":1489928737000,"endTime":1489928787000,"updated":1489928737000,"event":{"id":4,"description":"satish's Broadcast","type":"BROADCAST_PUBLIC","startTime":1489928737000,"endTime":1489928787000,"status":"FINISHED","eventReminderStatus":"NOT_SENT","updatedAt":1489928787000},"expectedDuration":0,"serviceProvider":"agora"}
Update:
broadcastData = {
...broadcast,
broadcaster: {
name: broadcast.user.name,
handle: broadcast.user.handle
},
channel: {
// channelName: broadcast.channel
},
likes: broadcast.broadcastStat.likes,
views: broadcast.broadcastStat.views,
}
Component 1
render() {
return (
<div className="flexslider tabs_slider no-slide">
<ul className="slides">
{this.state.Movies.map((item, index) => <Component2
key={item.db_recom_id}
item={item}
/>)}
</ul>
</div>
)
}
Component 2
render() {
return (
<li>
<img className="wrap_me" src={this.props.item.db_movies_img} />
)
}
Values that you specified in ques, are present directly inside object, you can access them by data.channel.any_key, data.description, data.recordedUrl.
If you want to print all the values of data.channel, then use map otherwise you can access directly by data.channel.channel.
Check this example:
let data = {
"id":4,
"user":{
"userId":1,
"chatUserId":0,
"handle":"satishkrypto",
"countryCode":"+971",
"phone":"569942359",
"picUrl":"https://ss-ap-southeast-1.amazonaws.com/production-speakerswire-images/user-profiles/male3x.png",
"userStat":{
"id":1,
"followers":4,
"followings":5,
"broadcastLikes":0,
"broadcastViews":90
},
"name":"satish verma",
"existingUser":false,
"userProfileImageType":"MALE",
"invitesLeft":4,
"userPriviledge":"SW_BROADCASTER"
},
"description":"satish's Broadcast",
"streamId":"pub11489928734882",
"audio":false,
"screenShotUrl":"https://ss-api-eb-dev.s3-ap-southeast-1.amazonaws.com/broadcast-images/pub11489928734882-1489928751454.jpg",
"recordedUrl":"https://production-ss-videos-red5pro.s3-ap-southeast-1.amazonaws.com/video/record/pub581489997130311.mp4",
"status":"RECORDED",
"type":"PUBLIC",
"locationEnabled":false,
"commentsEnabled":true,
"channel":{
"channelId":14,
"channel":"Productivity",
"color":"#4A148C",
"priority":986,
"created":1489922543000,
"updated":1489922543000,
"broadcast":0,"liveBroadcast":0
},
"broadcastStat":{
"id":4,
"likes":0,
"views":14,
"viewers":5,
"liveViewers":0
},
"latitude":0.0,
"longitude":0.0,
"startTime":1489928737000,
"endTime":1489928787000,
"updated":1489928737000,
"event":{
"id":4,
"description":"satish's Broadcast",
"type":"BROADCAST_PUBLIC",
"startTime":1489928737000,
"endTime":1489928787000,
"status":"FINISHED",
"eventReminderStatus":"NOT_SENT",
"updatedAt":1489928787000
},
"expectedDuration":0,
"serviceProvider":"agora"
};
class App extends React.Component{
render(){
return(
<div>
Channel Details: {Object.keys(data.channel).map(el=>{
return <p>{el}: {data.channel[el]}</p>
})}
Description: {data.description}
RecordedUrl: {data.recordedUrl}
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'/>