8

私はこのビデオをzindexで再生しています:-1ボタンとその上に浮かんだテキスト入力。問題は、テキストが変更されたとき、その状態オブジェクトを操作するはずであり、クリック可能なハイライトがクリック機能ではない場合です。機能したいときに機能します。私はこれをどのように修正すべきですか?

昨日の提案を使用すると、エラーが警告に変わります。入力ボックスに7つのランダムな文字を入力すると、「コンポーネントにメソッドをバインドしていることを警告します」という7つの警告が表示されます。これは、入力ボックスがタッチ可能なハイライトの機能を呼び出し続けていることを意味します。

私はこのライブラリをReact Nativeに使用して、ストリーミング機能を使用しています:https://github.com/oney/react-native-webrtc。それはかなり良いです!私は、テキストフィールドにテキストを入力すると

_renderTextRoom() { 
     return (
     <View style={styles.listViewContainer}> 

      <ListView 
      dataSource={this.ds.cloneWithRows(this.state.textRoomData)} 
      enableEmptySections={true} 
      renderRow={rowData => 
       <Text 
       style={styles.whiteOut} 
       >{`${rowData.user}: ${rowData.message}`}</Text>} 
      /> 

      <TextInput 
      style={[styles.whiteOut, styles.bgWhite]} 
      onChangeText={value => this.setState({ textRoomValue: value })} 
      value={this.state.textRoomValue} 
      /> 

      <View style={styles.buttonContainer}> 
      <TouchableHighlight 
       style={styles.button} 
       onPress={this._textRoomPress()}> 
       <Text style={styles.bgWhite}>Send</Text> 
      </TouchableHighlight> 
      </View> 

     </View> 
    ); 
    }, 

、this._textRoomPress()関数はTouchableHighlight内にネスト:それの例の一つで

https://github.com/oney/RCTWebRTCDemo/blob/master/main.js私はいじるいるコードのこれらの行があります発砲している。何!?私がコメントアウトすると、それは起動しません。

'use strict'; 

import React, { Component } from 'react'; 
import { 
    Dimensions, 
    StyleSheet, 
    Text, 
    TouchableHighlight, 
    View, 
    TextInput, 
    ListView, 
    ScrollView 
} from 'react-native'; 

import { userData } from '../utils/Factory'; 

import io from 'socket.io-client'; 

var socket_one = 'https://xxxxxxxxxxxxxx.herokuapp.com'; 

const socket = io.connect(socket_one, { transports: ['websocket'] }); 

import { 
    RTCPeerConnection, 
    RTCMediaStream, 
    RTCIceCandidate, 
    RTCSessionDescription, 
    RTCView, 
    MediaStreamTrack, 
    getUserMedia, 
} from 'react-native-webrtc'; 

const configuration = { "iceServers": [{ "url": "stun:stun.l.google.com:19302" }] }; 

const pcPeers = {}; 
let localStream; 

var width = Dimensions.get('window').width; //full width 
var height = Dimensions.get('window').height; //full height 

function getLocalStream(isFront, callback) { 

    MediaStreamTrack.getSources(sourceInfos => { 
    console.log(sourceInfos); 
    let videoSourceId; 
    for (const i = 0; i < sourceInfos.length; i++) { 
     const sourceInfo = sourceInfos[i]; 
     if (sourceInfo.kind == "video" && sourceInfo.facing == (isFront ? "front" : "back")) { 
     videoSourceId = sourceInfo.id; 
     } 
    } 

    getUserMedia({ 
     audio: true, 
     video: { 
     mandatory: { 
      minWidth: 700, // Provide your own width, height and frame rate here 
      minHeight: 700, 
      minFrameRate: 30 
     }, 
     facingMode: (isFront ? "user" : "environment"), 
     optional: [{ sourceId: sourceInfos.id }] 
     } 
    }, function(stream) { 
     console.log('dddd', stream); 
     callback(stream); 
    }, logError); 
    }); 

} 

function join(roomID) { 
    socket.emit('join', roomID, function(socketIds) { 
    console.log('join', socketIds); 
    for (const i in socketIds) { 
     const socketId = socketIds[i]; 
     createPC(socketId, true); 
    } 
    }); 
} 


function createPC(socketId, isOffer) { 
    const pc = new RTCPeerConnection(configuration); 
    pcPeers[socketId] = pc; 

    pc.onicecandidate = function(event) { 
    // console.warn('onicecandidate', event.candidate); 
    if (event.candidate) { 
     socket.emit('exchange', { 'to': socketId, 'candidate': event.candidate }); 
    } 
    }; 

    function createOffer() { 
    pc.createOffer(function(desc) { 
     console.log('createOffer', desc); 
     pc.setLocalDescription(desc, function() { 
     console.log('setLocalDescription', pc.localDescription); 
     socket.emit('exchange', { 'to': socketId, 'sdp': pc.localDescription }); 
     }, logError); 
    }, logError); 
    } 

    pc.onnegotiationneeded = function() { 
    console.log('onnegotiationneeded'); 
    if (isOffer) { 
     createOffer(); 
    } 
    } 

    pc.oniceconnectionstatechange = function(event) { 
    console.log('oniceconnectionstatechange', event.target.iceConnectionState); 
    if (event.target.iceConnectionState === 'completed') { 
     setTimeout(() => { 
     getStats(); 
     }, 1000); 
    } 
    if (event.target.iceConnectionState === 'connected') { 
     createDataChannel(); 
    } 
    }; 
    pc.onsignalingstatechange = function(event) { 
    console.log('onsignalingstatechange', event.target.signalingState); 
    }; 

    pc.onaddstream = function(event) { 
    console.log('onaddstream', event.stream); 
    // container.setState({ info: 'One peer join!' }); 
    container.setState({ info: 'Connected!' }); 

    const remoteList = container.state.remoteList; 
    remoteList[socketId] = event.stream.toURL(); 
    container.setState({ remoteList: remoteList }); 
    }; 
    pc.onremovestream = function(event) { 
    console.log('onremovestream', event.stream); 
    }; 

    pc.addStream(localStream); 

    function createDataChannel() { 
    if (pc.textDataChannel) { 
     return; 
    } 
    const dataChannel = pc.createDataChannel("text"); 

    dataChannel.onerror = function(error) { 
     console.log("dataChannel.onerror", error); 
    }; 

    dataChannel.onmessage = function(event) { 
     console.log("dataChannel.onmessage:", event.data); 
     container.receiveTextData({ user: socketId, message: event.data }); 
    }; 

    dataChannel.onopen = function() { 
     console.log('dataChannel.onopen'); 
     container.setState({ textRoomConnected: true }); 
    }; 

    dataChannel.onclose = function() { 
     console.log("dataChannel.onclose"); 
    }; 

    pc.textDataChannel = dataChannel; 
    } 
    return pc; 
} 

function exchange(data) { 
    const fromId = data.from; 
    let pc; 
    if (fromId in pcPeers) { 
    pc = pcPeers[fromId]; 
    } else { 
    pc = createPC(fromId, false); 
    } 

    if (data.sdp) { 
    console.log('exchange sdp', data); 
    pc.setRemoteDescription(new RTCSessionDescription(data.sdp), function() { 
     if (pc.remoteDescription.type == "offer") 
     pc.createAnswer(function(desc) { 
      console.log('createAnswer', desc); 
      pc.setLocalDescription(desc, function() { 
      console.log('setLocalDescription', pc.localDescription); 
      socket.emit('exchange', { 'to': fromId, 'sdp': pc.localDescription }); 
      }, logError); 
     }, logError); 
    }, logError); 
    } else { 
    console.log('exchange candidate', data); 
    pc.addIceCandidate(new RTCIceCandidate(data.candidate)); 
    } 
} 

function leave(socketId) { 
    console.log('leave', socketId); 
    const pc = pcPeers[socketId]; 
    const viewIndex = pc.viewIndex; 
    pc.close(); 
    delete pcPeers[socketId]; 

    const remoteList = container.state.remoteList; 
    delete remoteList[socketId] 
    container.setState({ remoteList: remoteList }); 
    container.setState({ info: 'One peer leave!' }); 
} 

socket.on('exchange', function(data) { 
    exchange(data); 
}); 
socket.on('leave', function(socketId) { 
    leave(socketId); 
}); 

socket.on('connect', function(data) { 
    console.log('connected'); 
}); 

function initStream() { 
    getLocalStream(true, function(stream) { 
    localStream = stream; 
    container.setState({ selfViewSrc: stream.toURL() }); 
    // container.setState({ status: 'ready', info: 'Please enter or create room ID' }); 
    container.setState({ status: 'connect', info: 'Connecting' }); 

    if (userData.inDanger) { 
     join(0); 
    } else { 
     join(userData.userName); 
     // join(userData.nowPlaying); 
    } 

    }); 

} 

function logError(error) { 
    console.log("logError", error); 
} 

function mapHash(hash, func) { 
    const array = []; 
    for (const key in hash) { 
    const obj = hash[key]; 
    array.push(func(obj, key)); 
    } 
    return array; 
} 

function _textRoomPress() { 
    if (!container.textRoomValue) { 
    return 
    } 
    const textRoomData = container.textRoomData.slice(); 
    textRoomData.push({ user: 'Me', message: container.textRoomValue }); 
    for (const key in pcPeers) { 
    const pc = pcPeers[key]; 
    pc.textDataChannel.send(container.textRoomValue); 
    } 
    container.setState({ textRoomData, textRoomValue: '' }); 
} 

function getStats() { 
    const pc = pcPeers[Object.keys(pcPeers)[0]]; 
    if (pc.getRemoteStreams()[0] && pc.getRemoteStreams()[0].getAudioTracks()[0]) { 
    const track = pc.getRemoteStreams()[0].getAudioTracks()[0]; 
    console.log('track', track); 
    pc.getStats(track, function(report) { 
     console.log('getStats report', report); 
    }, logError); 
    } 
} 

let container; 

const Stream = React.createClass({ 
    getInitialState: function() { 
    this.ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => true }); 
    return { 
     info: 'Initializing', 
     status: 'init', 
     roomID: '', 
     // isFront: true, 
     isFront: false, 
     selfViewSrc: null, 
     remoteList: {}, 
     textRoomConnected: false, 
     textRoomData: [], 
     textRoomValue: '', 
    }; 
    }, 
    componentDidMount: function() { 
    container = this; 
    initStream(); 
    }, 
    _press(event) { 
    // this.refs.roomID.blur(); 
    this.setState({ status: 'connect', info: 'Connecting' }); 
    join(userData.userName); 
    // join(this.state.roomID); 
    }, 
    _switchVideoType() { 
    const isFront = !this.state.isFront; 
    this.setState({ isFront }); 
    getLocalStream(isFront, function(stream) { 
     if (localStream) { 
     for (const id in pcPeers) { 
      const pc = pcPeers[id]; 
      pc && pc.removeStream(localStream); 
     } 
     localStream.release(); 
     } 
     localStream = stream; 
     container.setState({ selfViewSrc: stream.toURL() }); 

     for (const id in pcPeers) { 
     const pc = pcPeers[id]; 
     pc && pc.addStream(localStream); 
     } 
    }); 
    }, 
    receiveTextData(data) { 
    const textRoomData = this.state.textRoomData.slice(); 
    textRoomData.push(data); 
    this.setState({ textRoomData, textRoomValue: '' }); 
    }, 
    _textRoomPress() { 
    if (!this.state.textRoomValue) { 
     return 
    } 
    const textRoomData = this.state.textRoomData.slice(); 
    textRoomData.push({ user: 'Me', message: this.state.textRoomValue }); 
    for (const key in pcPeers) { 
     const pc = pcPeers[key]; 
     pc.textDataChannel.send(this.state.textRoomValue); 
    } 
    this.setState({ textRoomData, textRoomValue: '' }); 
    }, 
    _renderTextRoom() { 
    return (
     <View style={styles.listViewContainer}> 

       <ListView 
       dataSource={this.ds.cloneWithRows(this.state.textRoomData)} 
       enableEmptySections={true} 
       renderRow={rowData => 
        <Text 
        style={styles.whiteOut} 
        >{`${rowData.user}: ${rowData.message}`}</Text>} 
       /> 

       <TextInput 
       style={[styles.whiteOut, styles.bgWhite]} 
       onChangeText={value => this.setState({ textRoomValue: value })} 
       value={this.state.textRoomValue} 
       /> 


       <View style={styles.buttonContainer}> 
       <TouchableHighlight 
        style={styles.button} 
        onPress={this._textRoomPress()}> 
        <Text style={styles.bgWhite}>Send</Text> 
       </TouchableHighlight> 
       </View> 

      </View> 
    ); 
    }, 
    render() { 
    return (
     <View style={styles.container}> 
     { 
      mapHash(this.state.remoteList, (remote, index) => { 

      return (
       <ScrollView key={index}> 

       <RTCView key={index} streamURL={this.state.selfViewSrc} style={styles.remoteView}> 

       <View style={styles.buttonContainer}> 
        <TouchableHighlight 
        style={styles.button} 
        onPress={this._switchVideoType}> 
        <Text>Switch camera</Text> 
        </TouchableHighlight> 
       </View> 

       <View style={styles.bottomContainer}> 
        {this.state.textRoomConnected && this._renderTextRoom()} 
       </View> 

       </RTCView> 

      ) 

      }) 
     } 
     </View> 
    ); 
    } 
}); 

const styles = StyleSheet.create({ 
    container: { 
    flex: 10, 
    // justifyContent: 'center', 
    backgroundColor: 'rgba(0,0,0, .0)', 
    }, 
    topContainer: { 
    flex: 10, 
    backgroundColor: '#c7c7c7', 
    }, 
    bottomContainer: { 
    flex: 1, 
    justifyContent: 'flex-end', 
    // backgroundColor: '#ffeeff', 
    'zIndex': 1, 
    backgroundColor: 'rgba(0,0,0, .0)', 

    }, 
    selfView: { 
    width: 0, 
    height: 0 
    }, 
    remoteView: { 
    flex: 1, 
    'zIndex': -1, 
    // backgroundColor: '#c7c7c7', 
    backgroundColor: '#f0f0f0', 
    width: width, 
    height: height - 25, 
    resizeMode: 'stretch', // or 'stretch' 

    }, 
    welcome: { 
    fontSize: 20, 
    textAlign: 'center', 
    margin: 10, 
    }, 
    listViewContainer: { 
    height: 150, 
    }, 
    buttonContainer: { 
    height: 50, 
    // backgroundColor: 'powderblue', 
    justifyContent: 'center', 
    alignItems: 'center', 
    }, 
    button: { 
    marginTop: 50, 
    marginBottom: 50, 
    padding: 10, 
    paddingLeft: 30, 
    paddingRight: 30, 
    borderWidth: 1, 
    borderColor: 'rgba(0, 0, 0, .75)', 
    }, 
    whiteOut: { 
    // color: "#ffffff", 
    color: "#000", 
    }, 
    bgWhite: { 
    // backgroundColor: "#ffffff" 
    }, 
    listView: { 
    // backgroundColor: "#ffffff", 
    flex: 10, 
    // flexDirection: 'row', 
    // justifyContent: 'center', 
    // alignItems: 'center', 
    } 
}); 

export default Stream; 

答えて

7

それはそれはレンダリングが発行されるたびに発射され、任意に発射されていないthis._textRoomPress.bind(this)

に交換してください。これは、あなたがオブジェクトに渡すものが、渡される前に(関数のパラメータが基本的に)評価され、渡すものが関数の戻り値であるためです。もちろん、あなたのものではありません欲しいです。 this._textRoomPress(オブジェクトのコンテキストを保持する場合は、オプションのbind)を渡すことで、後で(要素が押されたとき)適切な時間にコンポーネントによって呼び出される関数への参照を渡します。

+1

自分自身を結合しないので、ES6矢印機能は、これが超簡単にします。推論は同じですが、関数を実行して戻り値に 'bind'を適用しています。あなたの関数は何も返さない可能性が高いので、 'undefined'を取得します。したがって、エラーです。 – martinarroyo

+0

最後の質問ですが、なぜこのエラーが発生しますか?私はそれが拘束力のある問題だと確信しています。 undefinedは評価するオブジェクトではありません( 'pc.textDataChannel.send')。時にはそれが動作し、サーバーにデータを送信しますが、ほとんどの場合、データはサーバーに送信されません。ありがとうございます@martinarroyo – clxxxii

+0

@clxxxiiそうかもしれないし、そうでないかもしれません。バインディングの問題は 'this'変数でアクセスする値にのみ影響します。そのような場合は、正しくバインドしていることを確認するか、コードを投稿して見てください。もう一つの可能​​性は、 'pc'か' textDataChannel'のどちらかが 'undefined'です。'undefined'値はプロパティを持たないため、アクセスできません。あなたがそれらの2つを更新している場所を確認してください(あなたは時にはそれが動作すると言いますから、あなたは何か値が変わっている可能性が高いと思います)。 – martinarroyo

3

あなたはes6構文ではなくcreateClassを使用しているので、すべてのメソッドはすでにコンポーネントに自動バインディングされています。あなたはそれが瞬時に、いつでもあなたのコンポーネントがレンダリングされる、その関数を呼び出しているonPress={this._textRoomPress()}>を使用する場合は

onPress={this._textRoomPress}> 

:単にちょうどにあなたたonPressを変更します。

+0

あなたは両方が正しいです!どうもありがとうございます! – clxxxii

2

<function name>()を使用すると、関数を呼び出すことができます...ここで何をしているのかは、それをonPressのpropに割り当てるのではなく、_renderTextRoom()が呼び出されるたびに呼び出されます。私が示唆しているのは、無名関数をthis._textRoomPressという呼び出しを返すよりも、(それを呼び出すことなく)小道具として渡すことです。 `this._textRoomPress.bind(この)`:彼らはのように、括弧を削除thismore info here

<View style={styles.buttonContainer}> 
    <TouchableHighlight 
     style={styles.button} 
     onPress={() => this._textRoomPress()}> 
     <Text style={styles.bgWhite}>Send</Text> 
    </TouchableHighlight> 
    </View> 
+0

皆さんはどちらも正しいです!どうもありがとうございます! – clxxxii

関連する問題