I want to show map in my React application. Here's codes:
export const App = () => {
useEffect(() => {
const view = new MapView(
{
map: new Map({ basemap: "arcgis-community"}),
container: "map",
center: [137.8239,36.2068],
zoom: 5,
}
);
}, [])
return (
<div className="App">
<div id='map'></div>
</div>
)
}
What I got:
Looking at the dev console:
I assume it is the MapView that creates 2 maps: esri-view-root and esri-view-root-storage. What's the reason for this behavior?
Related
I'm trying to build on the example app provided by livekit, so far I've implemented everything like the example app and I've been successful with connecting to a room on example website, I recieve audio from website, but I don't read the video stream, and I also can't send audio or video at all.
Steps to reproduce the behavior:
add the following to index.js
import { registerRootComponent } from "expo";
import { registerGlobals } from "livekit-react-native";
import App from "./App";
registerRootComponent(App);
registerGlobals();
Rendering the following component in App.tsx
import { Participant, Room, Track } from "livekit-client";
import {
useRoom,
useParticipant,
AudioSession,
VideoView,
} from "livekit-react-native";
import { useEffect, useState } from "react";
import { Text, ListRenderItem, StyleSheet, FlatList, View } from "react-native";
import { ParticipantView } from "./ParticipantView";
import { RoomControls } from "./RoomControls";
import type { TrackPublication } from "livekit-client";
const App = () => {
// Create a room state
const [, setIsConnected] = useState(false);
const [room] = useState(
() =>
new Room({
publishDefaults: { simulcast: false },
adaptiveStream: true,
})
);
// Get the participants from the room
const { participants } = useRoom(room);
const url = "[hard-coded-url]";
const token =
"[hard-coded-token";
useEffect(() => {
let connect = async () => {
// If you wish to configure audio, uncomment the following:
await AudioSession.configureAudio({
android: {
preferredOutputList: ["speaker"],
},
ios: {
defaultOutput: "speaker",
},
});
await AudioSession.startAudioSession();
await room.connect(url, token, {});
await room.localParticipant.setCameraEnabled(true);
await room.localParticipant.setMicrophoneEnabled(true);
await room.localParticipant.enableCameraAndMicrophone();
console.log("connected to ", url);
setIsConnected(true);
};
connect();
return () => {
room.disconnect();
AudioSession.stopAudioSession();
};
}, [url, token, room]);
// Setup views.
const stageView = participants.length > 0 && (
<ParticipantView participant={participants[0]} style={styles.stage} />
);
const renderParticipant: ListRenderItem<Participant> = ({ item }) => {
return (
<ParticipantView participant={item} style={styles.otherParticipantView} />
);
};
const otherParticipantsView = participants.length > 0 && (
<FlatList
data={participants}
renderItem={renderParticipant}
keyExtractor={(item) => item.sid}
horizontal={true}
style={styles.otherParticipantsList}
/>
);
const { cameraPublication, microphonePublication } = useParticipant(
room.localParticipant
);
return (
<View style={styles.container}>
{stageView}
{otherParticipantsView}
<RoomControls
micEnabled={isTrackEnabled(microphonePublication)}
setMicEnabled={(enabled: boolean) => {
room.localParticipant.setMicrophoneEnabled(enabled);
}}
cameraEnabled={isTrackEnabled(cameraPublication)}
setCameraEnabled={(enabled: boolean) => {
room.localParticipant.setCameraEnabled(enabled);
}}
onDisconnectClick={() => {
// navigation.pop();
console.log("disconnected");
}}
/>
</View>
);
};
function isTrackEnabled(pub?: TrackPublication): boolean {
return !(pub?.isMuted ?? true);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
stage: {
flex: 1,
width: "100%",
},
otherParticipantsList: {
width: "100%",
height: 150,
flexGrow: 0,
},
otherParticipantView: {
width: 150,
height: 150,
},
});
export default App;
the components used here are mostly the same as what's in the example, I've removed the screensharing logic and the messages
5. I run the app using an expo development build
6. it will log that it's connected, you'll be able to hear sound from the remote participant, but not see any video or send any sound.
7. if i try to add
await room.localParticipant.enableCameraAndMicrophone();
in the useEffect, I get the following error:
Possible Unhandled Promise Rejection (id: 0):
Error: Not implemented.
getSettings#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:103733:24
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:120307:109
generatorResume#[native code]
asyncGeneratorStep#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21908:26
_next#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21927:29
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21932:14
tryCallTwo#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26656:9
doResolve#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26788:25
Promise#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26675:14
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21924:25
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:120173:52
generatorResume#[native code]
asyncGeneratorStep#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21908:26
_next#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21927:29
tryCallOne#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26648:16
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26729:27
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27687:26
_callTimer#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27602:17
_callReactNativeMicrotasksPass#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27635:17
callReactNativeMicrotasks#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27799:44
__callReactNativeMicrotasks#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21006:46
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:20806:45
__guard#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:20986:15
flushedQueue#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:20805:21
flushedQueue#[native code]
Expected behavior
This should both receive & send video and audio streams between the two clients
I'm new working with THREE.js and I've been trying to show a .glb model into my component.
<template>
<section id="hero"></section>
</template>
<script>
import * as THREE from "three";
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
//import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { onMounted } from '#vue/runtime-core';
export default {
setup(){
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight,0.1,10);
let renderer = new THREE.WebGLRenderer();
let light = new THREE.AmbientLight( 0x404040 );
let loader = new GLTFLoader();
const init = ()=>{
renderer.setSize(window.innerWidth, window.innerHeight);
loader.load(
process.env.BASE_URL+'GLB/Elephant.glb',
function (glb ) {
console.log(glb);
scene.add(glb.scene);
light.position.set(2,2,5);
scene.add(light);
},
function (xhr) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
function (error) {
console.error( error );
}
);
const container = document.getElementById('hero');
container.appendChild(renderer.domElement);
camera.position.set(0,1,2)
};
const animate = () => {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
onMounted(()=>{
init();
animate();
})
}
}
</script>
<style>
#hero {
width: 100%;
height: 100vh;
background-color: white;
}
</style>
I know that my .glb file is loaded because it's show in the console. but when I add it to my scene there is nothing in the screen, I've also tried with the example from the documentation where I can show the cube from the example but when is a custom model it is not working, I don't have any error in the console.
maybe your camera's position is not good. If you don't set where the camera look at ,the camera will look at (0, 0, 0) by default, if your model is out of sight, you will not see it. You can add a controller to change your perspective.
`setup(){
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight,0.1,10);
let renderer = new THREE.WebGLRenderer();
let light = new THREE.AmbientLight( 0x404040 );
let loader = new GLTFLoader();
const init = ()=>{
renderer.setSize(window.innerWidth, window.innerHeight);
loader.load(
process.env.BASE_URL+'GLB/Elephant.glb',
function (glb ) {
console.log(glb);
scene.add(glb.scene);
light.position.set(2,2,5);
scene.add(light);
},
function (xhr) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
function (error) {
console.error( error );
}
);
const controls = new OrbitControls(camera, renderer.domElement)
const container = document.getElementById('hero');
container.appendChild(renderer.domElement);
camera.position.set(0,1,2)
};
const animate = () => {
requestAnimationFrame( animate );
renderer.render( scene, camera );
controls.update();
};
onMounted(()=>{
init();
animate();
})
}`
if this is not working, you should consider if the size of model is too big/small. you can use
const box = new THREE.Box3().setFromObject(glb.scene);
console.log(box)
to check the size of it, and use glb.scene.scale.set()to set its scale.
I am trying to show in the app that I built in React a PDF file using PDFtron and encounter the following error: Two instances of WebViewer were created on the same HTML element. Please create a new element for each instance of WebViewer.
my code is:
import { url } from "../../../../config.json";
import React, { useState, useEffect, useRef } from "react";
import { getProject } from "../../../../services/projectService";
import { useParams } from "react-router-dom";
import WebViewer from "#pdftron/webviewer";
import { getCurrentUser } from "../../../../services/userService";
import { Link, Redirect } from "react-router-dom";
import { deleteImage } from "../../../../services/projectService";
const MyContracts = () => {
const [project, setProject] = useState({});
const [counter, setCounter] = useState(0);
const [files, setFiles] = useState([]);
const { id } = useParams();
// const viewerDiv = useRef();
const user = getCurrentUser();
const [viewerUrl, setViewerUrl] = useState(`${url}/files/testing.pdf`);
const viewer = document.getElementById("viewer");
useEffect(() => {
getProject(id)
.then(res => {
setProject(res.data);
setFiles(res.data.files.contracts);
})
.catch(error => console.log(error.message));
}, []);
useEffect(() => {
if (files.length > 0) {
WebViewer(
{
path: `${url}/lib`,
initialDoc: `${url}/files/testing.pdf`,
fullAPI: true,
},
viewer
).then(async instance => {
const { docViewer } = instance;
docViewer.getDocument(viewerUrl);
});
}
}, [files, viewerUrl]);
if (!user) return <Redirect to="/private-area/sign-in" />;
if (user && user.isAdmin | (user._id === project.userID))
return (
<div className="container">
</div>
{/********** PDF VIEWER ************/}
<div className="web-viewer" id="viewer"></div>
{/* <div className="web-viewer" ref={viewerDiv} id="viewer"></div> */}
{/********** PDF Gallery ************/}
{files !== undefined && (
<>
<h2 className="text-rtl h3Title mt-2">בחר קובץ</h2>
<select
id="select"
className="col-12 text-rtl px-0"
onChange={e => setViewerUrl(e.target.value)}>
{files.map((file, index) => (
<option value={`${url}${file.url}`} key={index}>
{file.name}
</option>
))}
</select>
</>
)}
</div>
);
};
export default MyContracts;
What am I doing wrong and how can I fix it?
I see that you are trying to load multiple instances of WebViewer:
useEffect(() => {
if (files.length > 0) {
WebViewer(
{
path: `${url}/lib`,
initialDoc: `${url}/files/testing.pdf`,
fullAPI: true,
},
viewer
).then(async instance => {
const { docViewer } = instance;
docViewer.getDocument(viewerUrl);
});
}
}, [files, viewerUrl]);
Webviewer cannot be instantiated more than once in the same HTML element. If you need a completely different instance, you can hide or remove the HTML element and create a new one to hold the new instance.
That being said, if you just need to load another document, I would recommend using the loadDocument API. You can read more about it here as well.
I'm facing an issue on the code below (sandbox here https://codesandbox.io/s/silly-rubin-9ghc5?fontsize=14&hidenavigation=1&theme=dark ), the props change but doesn't refresh the component accordingly.
I would like to be able to keep track of different votes / options within a state in the parent node, hence i'm using an array where the index is the index of my option and the value the number of votes.
import { useEffect, useState } from "react";
import { Button, View } from "react-native";
import "./styles.css";
const myList = [
{
cid: 0,
cTx: "Paris"
},
{
cid: 1,
cTx: "Lyon"
},
{
cid: 2,
cTx: "Marseille"
},
{
cid: 3,
cTx: "Valence"
},
{
cid: 4,
cTx: "Bordeaux"
}
];
interface mTprop {
myItemId: number;
myItemTxt: string;
myItemSt: number[];
myItemClck: () => void;
}
const MyItem = (props: mTprop) => {
const onBtPress = () => {
props.myItemClck();
console.log(props.myItemSt);
};
return (
<View
style={{
flexDirection: "row"
}}
>
<h3>{props.myItemTxt}</h3>
<Button onPress={onBtPress} title="Learn More" />
<h3>{props.myItemSt[props.myItemId]}</h3>
</View>
);
};
export default function App() {
const [selectedOpt, setSelectedOpts] = useState(new Array(0));
useEffect(() => {
setSelectedOpts(new Array(myList.length).fill(0));
}, []);
const updateOptions = (ix: number) => {
++selectedOpt[ix];
setSelectedOpts(selectedOpt);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
{myList.map((itm, ix) => {
return (
<MyItem
key={ix}
myItemId={ix}
myItemTxt={itm.cTx}
myItemSt={selectedOpt}
myItemClck={() => updateOptions(ix)}
/>
);
})}
</div>
);
}
Thanks a million in advance !
Please let me know if further info is needed
In order to change data in list. You need to do this
const updateOptions = (ix: number) => {
const newList = selectedOpt.map((m, i) => {
if (i === ix) {
return m + 1;
}
return m;
});
setSelectedOpts(newList);
};
Ok, so i just started out with React Native and googled the subject I was able to make this:
index.ios.js:
var React = require('react-native');
var { AppRegistry } = React;
var MarvelsApp = require('./components/start');
AppRegistry.registerComponent('MarvelsApp', () => MarvelsApp);
start.js:
'use strict';
var React = require('react-native');
var {
Text,
View,
Image,
TextInput,
StatusBar,
ListView
} = React;
var b = 'https://api.themoviedb.org/3/movie/popular?api_key=XXXXXX';
console.log('api url',b);
var stylesStart = React.StyleSheet.create({
container: {
backgroundColor: 'pink',
flex: 1
},
test: {
color: 'black',
fontSize: 22
}
});
var Start = React.createClass({
getInitialState() {
return {
movie: [],
};
},
componentDidMount: function() {
this.fetchData();
},
fetchData: function(){
fetch(b)
.then((response) => response.json())
.then((data) => {
console.log('Logging api response', data.results);
this.setState({
movie: data
});
})
.done();
},
render: function() {
return (
<View style={stylesStart.container}>
<StatusBar barStyle="light-content"/>
<Text style={stylesStart.test}>{this.state.movie.title}</Text>
</View>
);
}
});
module.exports = Start;
Basically what I am trying to achieve is to make an http request using the api from themoviedb.org. And then to display the retrieved data in the view.
So far I am able to pull in the data via the http request but I am not having much luck showing it in the view. Now this could be because I missed a step or because I am doing it wrong.
Please point out to me where or what I am doing wrong
You are accessing the wrong key from this.state, try logging this.state and see the structure of it. You'll probably need to call this.state.movie[0].title to see the title.
you init the state variable movie as an array
(return {movie: [],};),
but you use it as an object (this.state.movie.title),
finally, you update the state (this.setState({movie: data});)
make sure the type you use are you need.
if you want to render as a list , the state variable movie should be an array, or you just want to render a item ,it could be an object