2014-10-08 17 views
7

voglio cambiare manifesto sorgente video e VideoJS quando selectedVideo cambiatoReactJS non possono cambiare il video e il poster videojs

var VideoPlayer = React.createClass({ 
    render: function() { 
    var selectedVideo = this.props.selectedVideo; 
    function filterVideo(video) { 
     return video.id == selectedVideo; 
    } 

    var data = this.props.videos.filter(filterVideo); 
    return (
     <div className="col-md-6 videoplayer"> 
     <h2>{data[0].title}</h2> 
     <video id="videoplayer" className="video-js vjs-default-skin vjs-big-play-centered" controls preload="none" 
      width="100%" 
      height="300" 
      poster={data[0].poster} 
      data-setup="{}"> 
      <source src={data[0].video} type='video/mp4' /> 
     </video> 
     <div className="video-description"> 
      {data[0].description} 
     </div> 
     </div> 
    ); 
    } 
}); 

ma ho ottenuto l'errore:

Uncaught Error: Invariant Violation: ReactMount: Two valid but unequal nodes with the same `data-reactid`: .0.0.1.1 

titolo e una descrizione cambiato, ma il poster video non cambia

risposta

16

Questo è un problema con le librerie distruttive. Fondamentalmente ciò che accade è il rendering dell'elemento <video>, quindi VideoJS inietta un gruppo di elementi accanto al tuo <video> (gli elementi figlio vanno bene).

React tenta di aggiornare l'elemento e non riesce a capire cosa sta succedendo, quindi va in panico e dà quell'errore.

in modo da avere due opzioni:

Opzione 1: rendere un <div ref="target" />, costruire il nodo video nel componentDidMount e this.refs.target.appendChild(that), e quindi richiamare VideoJS manualmente. In componentWillRecieveProps è necessario aggiornare direttamente il poster img's src.

Opzione 2: fork video.js e farlo emettere solo eventi invece di modificare direttamente il DOM. Il tuo componente reagirebbe a quegli eventi, modificando lo stato e rendendo manifesto, pulsanti, ecc.

L'opzione 1 è più semplice, l'opzione 2 è potenzialmente più efficiente e più pulita. Mi piacerebbe andare con l'opzione 1.


Nessuno di questi sono buone soluzioni, ma le librerie che sfuggono loro contenitore non giocare bene con reagire.

+1

grazie, per la tua bella risposta :) –

+0

Ha funzionato come un fascino, grazie. –

+0

@fakerainbrigand puoi fornire un esempio? In particolare per quanto riguarda componentWillReceiveProps e cleanup? https://github.com/videojs/video.js/issues/2006 – chemoish

11

Nel caso qualcuno abbia bisogno di un esempio della risposta di FakeRainBrigand, ecco come appare la mia classe video alla fine.

Video = React.createClass({ 
    componentDidMount: function() { 
    var video, wrapper; 
    wrapper = document.createElement('div'); 
    wrapper.innerHTML = "<video id='attachmentVideo' class='video-js vjs-default-skin' controls preload='auto' width='640' height='264' poster='" + this.props.thumbnail + "'><source src='" + this.props.url + "' type='video/mp4' /><p className='vjs-no-js'>To view this video please enable JavaScript, and consider upgrading to a web browser that <a href='http://videojs.com/html5-video-support/' target='_blank'>supports HTML5 video</a></p></video>"; 
    video = wrapper.firstChild; 
    this.refs.target.getDOMNode().appendChild(video); 
    return videojs(video, {}); 
    }, 
    render: function() { 
    return (
     <div id="attachmentViewer"> 
     <h2>{this.props.title}</h2> 
     <div id="attachmentVideoContainer" ref="target" /> 
     </div> 
    ); 
    } 
}); 
0

non al 100% relativo, ma se siete alla ricerca di una più "pura" reagire soluzione per implementare videoJS come componente, questo è quello che ho fatto ...

L'ultimo post è stato un tempo fa e non so se qualcuno si avvicinò con una migliore attuazione, tuttavia, quello che ho fatto è stata la seguente:

  1. aggiunta la funzione videojs come un puntello getInitialState e ha aggiunto un "videoHTML" riferita al getInitialState anche.
  2. Ho generato il mio tag video e le mie origini nel metodo componentDidMount e assegnato quella stringa variabile allo stato del videoHTML.
  3. Aggiunto un dispose() del player vjs istanziato e un replaceState dello stato iniziale al metodo componentWillUnmount().
  4. Aggiunta una funzione componente __initVideo (elem) che controlla se l'elemento passato ha figli e se fa "this.vjsPlayer = this.state.initVideoJS (elem.children [0], {})". Quindi restituisco this.vjsPlayer.
  5. Nel div allegato, nel metodo render(), imposto il puntello pericolosamenteSetInnerHTML al puntello this.state.videoHTML e imposta un riferimento che richiama la funzione __initVideo, passando nel div.

Impossibile postare alcun codice, ma questo è il più vicino a una pura implementazione React di videoJS che sono stato in grado di capire.