2016-12-13 6 views
3

Я новичок в реакцииJS и пытаюсь построить компонент.Как передать веб-камеру на веб-страницу с помощью компонента js-ответа?

Я хочу создать базовую утилиту, в которой у меня есть видеокомпонент, который показывает канал живой веб-камеры, и была бы кнопка захвата, чтобы захватить и сохранить привязку фида на диск. Я хочу, чтобы это было в одном компоненте (видео подачи + кнопка захвата)

Этот код потоков фид в браузере, но я хочу его в компоненте,

<body> 
<div id="container"> 
    <video autoplay="true" id="videoElement"> 

    </video> 
</div> 
<script> 
var video = document.querySelector("#videoElement"); 

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia; 

if (navigator.getUserMedia) {  
    navigator.getUserMedia({video: true}, handleVideo, videoError); 
} 

function handleVideo(stream) { 
    video.src = window.URL.createObjectURL(stream); 
} 

function videoError(e) {} 
</script> 
</body> 
</html> 

Это прекрасно работает, но не это не компонент.

Я попробовал следующее reaact JS, но это не работает:

<body> 
    <div id="container"> 

    </div> 
    <script type="text/jsx"> 
     var MyComponent = React.createClass({ 
      handleVideo: function(stream) { 
       video.src = window.URL.createObjectURL(stream); 
      }, 
      videoError: function() { 

      }, 
      render: function() { 

      var video = document.querySelector("#videoElement"); 

      navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia; 

      if (navigator.getUserMedia) {  
       navigator.getUserMedia({video: true}, this.handleVideo, this.videoError); 
      } 
       return <div> 
         <video autoplay="true" id="videoElement"> 
         </video> 
         </div>; 
      } 
     }); 
    React.render(<MyComponent />, document.getElementById('container')); 
    </script> 
    </body> 

Ошибка в handleVideo()

ReferenceError: видео не определен.

Мое понимание ошибки,

, так как тег видео приходит в более поздней части (взамен), он пытается использовать перед определением в функции handleVideo. Я смущен, как сделать эту работу.

Спасибо!

+0

я не включил это в моем ответе, так как это на самом деле не часть ответа, но это выглядит как из кода, который вы ставите ваш React кода в соответствии с вашим HTML. JSX предназначен для использования в файлах Javascript, и, хотя вы * можете * поместить его в свой HTML, вы, вероятно, получите больше успеха, сохраняя свой код компонента в отдельном файле. Ваша IDE не будет смущена двумя синтаксисами, подобными HTML, в том же файле, будет проще использовать такие инструменты, как Babel, для преобразования вашего JSX в дружественный браузер JS и т. Д. – machineghost

+0

Спасибо, Я планирую поставить код реакции в другом файле, но я думал, что могу сначала запустить треск, а затем создать дополнительную функциональность с отдельными файлами. Я просто изучаю с помощью Youtube видеоуроков, и вот как я начал, улучшив код в том же файле. :) –

ответ

4

Есть несколько вещей, чтобы понять, как работают компоненты React. Во-первых, в соответствии с React docs:

The render() function should be pure, meaning that it does not modify component state, it returns the same result each time it's invoked, and it does not directly interact with the browser.

Вы должны переместить инициализацию видео элемент на альтернативный метод, как жизненный цикл componentDidMount, чтобы убедиться, что он только инициализируется один раз.

Во-вторых, вам редко нужно напрямую взаимодействовать с DOM. В этом случае мы можем использовать внутреннее состояние компонента для управления атрибутом src для видеопотока, гарантируя, что он будет обновляться только после инициализации потока.

Вот обновленный компонент, который может работать:

var MyComponent = React.createClass({ 
    getInitialState: function(){ 
    return { videoSrc: null } 
    }, 
    componentDidMount: function(){ 
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia; 
    if (navigator.getUserMedia) { 
     navigator.getUserMedia({video: true}, this.handleVideo, this.videoError); 
    } 
    }, 
    handleVideo: function(stream) { 
    // Update the state, triggering the component to re-render with the correct stream 
    this.setState({ videoSrc: window.URL.createObjectURL(stream) }); 
    }, 
    videoError: function() { 

    }, 
    render: function() { 
    return <div> 
     <video src={this.state.videoSrc} autoPlay="true" /> 
    </div>; 
    } 
}); 
+0

Hi @jordan, Благодарим вас за ответ, «componentDidMount» - это то, что я искал. Я согласен, что функция рендеринга должна сохраняться чистой :) Я пробовал код, предложенный здесь выше. Я не вижу ошибок в консоли, но видеокомпонент отсутствует на странице. Это доступ к веб-камера, (свет включен), но видео компонент отсутствует :( Мысли? –

+0

Я добавил '«ID = videoElement»' и видео компонент вернулся. Теперь он также имеет src, но так или иначе, поле пусто. Lol –

+1

Вы видели ошибки в консоли отладки? См. мой отредактированный ответ для версии, которую я тестировал. Вам нужно убедиться, что функция «videoError» все еще существует. Также '' autoplay' становится autoPlay' –

2

Ваш handleVideo метод ссылается video, но вы не определяете эту переменную где-нибудь handleVideo. Вместо этого, вы определяете его в render:

var video = document.querySelector("#videoElement"); 

Таким образом, есть ваша первая проблема, но это не ваша реальная проблема. Ваша реальная проблема заключается в том, что в React-land вы хотите избежать document.anything (getElementById, getByTagAndClassName, querySelector и т. Д.). Это связано с тем, что React использует виртуальную DOM, и если вы не будете осторожны, когда ссылаетесь на фактические элементы DOM, эти ссылки могут быстро ухудшаться (поскольку виртуальный DOM заменяет фактическую DOM после render).

Решение состоит в том, чтобы использовать альтернативную технику Реагента: refs. Они легче объяснить, например, так вот ваш код исправляются refs:

handleVideo: function(stream) { 
    // KEY CHANGE #1 
    this.refs.video.src = window.URL.createObjectURL(stream); 
}, 
render: function() { 
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia; 

    if (navigator.getUserMedia) {  
     navigator.getUserMedia({video: true}, this.handleVideo, this.videoError); 
    } 
    return <div> 
     {{/* KEY CHANGE #2 */}} 
     <video autoplay="true" id="videoElement" ref="video"> 
     </video> 
    </div>; 

Другими словами, если добавить атрибут ref="something" к любому элементу, вы возвращаете в вашей render функции, вы можете ссылаться на этот элемент в любом месте еще в вашем (React) коде, обратившись к this.refs.something.

Там также другие способы использования refs (например, вы можете передать функцию.), Но это выходит за рамки данного вопроса, поэтому я просто рекомендую прочитать на React документы для refs:

https://facebook.github.io/react/docs/refs-and-the-dom.html

EDIT

В ответ Джордан Бернетт подчеркнул, существуют и другие важные различия между React и нормальной работы JS DOM.Опять же, объясняя все из них выходит за рамки этого вопроса, но я настоятельно рекомендую вам прочитать:.

https://facebook.github.io/react/docs/react-component.html

изучить соответствующие методы, чтобы переопределить, чтобы сделать работу DOM-взаимодействия (например, связывание событий обработчики на компонентах без реактивов).

+0

Спасибо @machineghost за ваш ответ. Я рассмотрю документы, упомянутые выше. Я уверен, что это поможет мне. –

+0

На данный момент я внесли изменения, которые вы предложили использовать «ref» Теперь сообщение об ошибке с консоли исчезло, но я не вижу канал в моем браузере. это просто пустая коробка. Тем не менее, загорается веб-камера. Мысли? –

+1

Похоже, что «src» видео не устанавливается (я думаю, что '