Gathering detailed insights and metrics for simple-p2p-webrtc
Gathering detailed insights and metrics for simple-p2p-webrtc
Gathering detailed insights and metrics for simple-p2p-webrtc
Gathering detailed insights and metrics for simple-p2p-webrtc
simple-peer
Simple one-to-one WebRTC video/voice and data channels
@thaunknown/simple-peer
Simple one-to-one WebRTC video/voice and data channels
simple-peer-light
Simple, light-weight WebRTC video/voice and data channels
@vandeurenglenn/simple-peer
Simple one-to-one WebRTC video/voice and data channels
Simple WebRTC peer-to-peer connections in both React Native and React apps.
npm install simple-p2p-webrtc
Typescript
Module System
TypeScript (100%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
1 Stars
14 Commits
1 Watchers
1 Branches
1 Contributors
Updated on Apr 27, 2025
Latest Version
1.1.0
Package Id
simple-p2p-webrtc@1.1.0
Unpacked Size
43.16 kB
Size
6.94 kB
File Count
16
Published on
Sep 29, 2024
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
3
This package provides a WebRTC wrapper implementation for both React(tested w/ Next) and React Native applications, enabling peer-to-peer (P2P) data communication. It abstracts the WebRTC integration into React-based projects, both cjs and mjs available.
1npm install simple-p2p-webrtc 2# or 3yarn add simple-p2p-webrtc
There are both hook and class implementations for React and React Native apps, same interface with dependency injection under the hood.
To make the connection process smoother you can use a signaling server.
For simplicity below example acts as a counterpart to the following application in Next.js. It initiates the p2p connection. The offer is then provided to the next app.
1import { useEffect, useState } from 'react'; 2import { Button, Keyboard, StyleSheet, Text, TextInput, View } from 'react-native'; 3import { usePeer } from 'simple-p2p-webrtc/react-native'; 4 5const UPDATE_INTERVAL = 300; // optional 6const RTC_CONF = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }; // you have to provide stun servers 7const CHAN = "data"; // channel descriptor to be used 8 9export default function App() { 10 // creating peer 11 const peer = usePeer(RTC_CONF, undefined, UPDATE_INTERVAL); // second argument is the msg callback 12 // update interval is optional 13 const { dataChannelState, connectionState } = peer; // destructure 14 15 const [answer, setAnswer] = useState(''); 16 const [offer, setOffer] = useState(''); 17 const [ice, setIce] = useState<RTCIceCandidate[]>([]); 18 19 useEffect(() => { 20 if (dataChannelState === "open") { 21 try { 22 peer.send("PING"); // ping once connected 23 } catch (e) { 24 console.log('Connection severed'); // you dont have to log errors but can handle them 25 } 26 } 27 }, [dataChannelState]); 28 29 const handleCreateOffer = async () => { 30 try { 31 peer.createDataChannel(CHAN); 32 const offer = await peer.createOffer(); 33 setOffer(offer); 34 } catch (e) { 35 console.error("Error creating offer", e); 36 } 37 }; 38 39 const handleSetIceCandidates = async () => { 40 try { 41 for (const iceCand of ice) { 42 await peer.addRemoteIceCandidate(iceCand); 43 } 44 } catch (e) { 45 console.error("Error setting ICE candidates", e); 46 } 47 }; 48 49 const handleSetRemoteDescription = async () => { 50 try { 51 await peer.setRemoteDescription(answer); 52 } catch (e) { 53 console.error("Error setting remote description", e); 54 } 55 }; 56 57 return ( 58 <View style={styles.container}> 59 <Text> Connect</Text> 60 <Text>Connection state: {connectionState}</Text> 61 <Text>Data channel state: {dataChannelState}</Text> 62 {["closed", "create"].includes(dataChannelState) ? 63 <> 64 <Button title="Create Offer" onPress={handleCreateOffer} /> 65 {offer && <TextInput 66 returnKeyType="done" 67 onSubmitEditing={() => Keyboard.dismiss()} 68 value={offer} 69 multiline 70 style={styles.input} 71 />} 72 73 <TextInput 74 returnKeyType="done" 75 onSubmitEditing={() => Keyboard.dismiss()} 76 value={answer} 77 onChangeText={setAnswer} 78 placeholder="Paste Answer" 79 style={styles.input} 80 /> 81 <Button title="Set Remote Description" onPress={handleSetRemoteDescription} /> 82 83 <TextInput 84 returnKeyType="done" 85 onSubmitEditing={() => Keyboard.dismiss()} 86 value={JSON.stringify(ice)} 87 onChangeText={(s) => setIce(JSON.parse(s))} 88 placeholder="Paste Ice Candidates" 89 style={styles.input} 90 /> 91 <Button title="Set Ice Candidates" onPress={handleSetIceCandidates} /> 92 </> : 93 <Text>Data is being sent to the web client!</Text>} 94 </View> 95 ); 96} 97 98const styles = StyleSheet.create({ 99 container: { 100 flex: 1, 101 paddingTop: 100, 102 backgroundColor: '#fff', 103 alignItems: 'center', 104 }, 105 input: { 106 height: 40, 107 borderColor: 'gray', 108 borderWidth: 1, 109 marginVertical: 10, 110 width: '80%', 111 padding: 10, 112 }, 113});
The Next.js app receives an offer and generates an answer along with providing ice candidates for connection. Both the answer and the ice candidates need to be fed back to the react native app, typically this is done through a signaling server.
1"use client" // we need to be a client component/ page 2 3import { useEffect, useState } from "react"; 4import { usePeer } from "simple-p2p-webrtc"; 5 6const RTC_CONF = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }; // stun servers 7const UPDATE_INTERVAL = 300; // optional 8 9export default function Home() { 10 const [data, setData] = useState<string>(''); 11 const [offer, setOffer] = useState<string>(''); 12 const [answer, setAnswer] = useState<string>(''); 13 const peer = usePeer(RTC_CONF, (msg) => { 14 setData(msg); // message callback 15 // data will be ping 16 // set once 17 }, UPDATE_INTERVAL); 18 const { connectionState, dataChannelState, iceCandidates } = peer; 19 20 return ( 21 <div className="min-h-screen w-full flex flex-col items-center justify-center bg-gray-100 p-4 text-black"> 22 <p className="mb-4">Connection status: {connectionState}</p> 23 <p className="mb-4">Data chan status: {dataChannelState}</p> 24 25 {(dataChannelState == 'closed') ? // automatically set to closed when initialized with msgCallback because we are looking for a dataChannel 26 <> 27 <form onSubmit={async (e) => { 28 e.preventDefault(); 29 try { 30 setAnswer((await peer.createAnswer(offer))); // an answer to the offer is created and shown 31 } catch (e) { 32 console.error(e); 33 } 34 }} className="mb-4 flex flex-col"> 35 <textarea 36 value={offer} 37 onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setOffer(e.target.value)} 38 placeholder="Paste the offer from the React Native app here" 39 className="w-64 h-32 p-2 border rounded" 40 /> 41 <button type="submit" className="mt-2 px-4 py-2 bg-blue-500 text-white rounded"> 42 Connect 43 </button> 44 </form> 45 {(answer && peer) && ( 46 <div className="mb-4"> 47 <h2 className="text-lg font-semibold">Answer & Ice Candidates:</h2> 48 <textarea 49 value={answer} 50 readOnly 51 className="w-64 h-32 p-2 border rounded" 52 /> 53 <textarea 54 value={JSON.stringify(iceCandidates)} 55 readOnly 56 className="w-64 h-32 p-2 border rounded" 57 /> 58 </div> 59 )} 60 </> : 61 <> 62 <p>Receiving data</p> 63 </> 64 } 65 </div> 66 ); 67};
License is MIT. Feel free to contribute.
No vulnerabilities found.
No security vulnerabilities found.