2017-09-26 42 views
0

我想在這個燈箱接受組件以及圖像使用視頻播放器(即可以顯示任意數量的不同視頻):如何動態更新的子組件的屬性

lightbox-react

他們文檔給出了一個簡單的例子(粘貼在下面),忽略了一個重要的細節:一個組件可能需要在顯示時改變其內容的一部分。所以我需要了解如何將屬性傳遞給用於Lightbox的mainSrc屬性的組件。

我是React的新手,所以我想學習正確的方法來管理這個。我能找到,將工作對我來說唯一的語法是,在父:

constructor(props) { 
    super(props); 
    this.state = { 
    myVidPlayer: '', 
    } 
} 
... 
handleLightboxOpen() { 
    this.setState({ 
    // re-create new video player every time: 
    myVidPlayer: React.createElement(VidPlayer, { vidSrc: **real video source here** }), 
    }); 
} 

而且在渲染燈箱父的,我只是有<Lightbox mainSrc={this.state.myVidPlayer}...>按照需要做的工作,但我重建每當燈箱彈出時,子組件都會顯示錯誤。

我試着這樣做:

constructor(props) { 
    super(props); 
    this.state = { 
    myVidSrc: '', 
    } 
    this.vidPlayer = React.createElement(VidPlayer, { vidSrc: this.state.myVidSrc }); 
} 
... 
handleLightboxOpen() { 
    this.setState({ 
    // does not work, child does not get updated: 
    myVidSrc: '**real video source here**', 
    }); 
} 

而且在渲染燈箱父,<Lightbox mainSrc={this.vidPlayer}...>但子組件「vidSrc」的當父狀態變量改變道具永遠不會被更新。我一直認爲這應該會泡沫化,但在這種情況下,支柱似乎仍然處於初始值。

他們的示例代碼如下(我更換「VideoIframe」我自己「vidPlayer」每以上):

import React, { Component } from 'react'; 
import Lightbox from 'lightbox-react'; 
import VideoIframe from 'components/cat-video'; 

const images = [ 
    VideoIframe, 
    '//placekitten.com/1500/500', 
    '//placekitten.com/4000/3000', 
    '//placekitten.com/800/1200', 
    '//placekitten.com/1500/1500' 
]; 

export default class LightboxExample extends Component { 
    constructor(props) { 
     super(props); 

     this.state = { 
      photoIndex: 0, 
      isOpen: false 
     }; 
    } 

    render() { 
     const { 
      photoIndex, 
      isOpen, 
     } = this.state; 

     return (
      <div> 
       <button 
        type="button" 
        onClick={() => this.setState({ isOpen: true })} 
       > 
        Open Lightbox 
       </button> 

       {isOpen && 
        <Lightbox 
         mainSrc={images[photoIndex]} 
         nextSrc={images[(photoIndex + 1) % images.length]} 
         prevSrc={images[(photoIndex + images.length - 1) % images.length]} 

         onCloseRequest={() => this.setState({ isOpen: false })} 
         onMovePrevRequest={() => this.setState({ 
          photoIndex: (photoIndex + images.length - 1) % images.length, 
         })} 
         onMoveNextRequest={() => this.setState({ 
          photoIndex: (photoIndex + 1) % images.length, 
         })} 
        /> 
       } 
      </div> 
     ); 
    } 
} 
+0

您不能在組件內部以外的任何位置更改組件的狀態。試圖這樣做是一個主要的反模式。 – gravityplanx

+0

@gravityplanx好吧,我明白了,但請查看問題的要點,如何更改該組件中的視頻源。所以也許我應該使用的詞是「改變屬性/屬性」? – messy

+0

您需要製作一個具有該選項的不同組件。 'VideoIFrame'只是一個硬編碼的視頻例子,它並不意味着用於實際目的。儘管你可以在這裏看到該組件的內部; https://github.com/treyhuffine/lightbox-react/blob/master/src/examples/cats/components/video.js – gravityplanx

回答

0

感謝提供更新。

將道具從父母傳遞給孩子是反應的一個基本方面,對理解非常重要。一個簡單的例子可能看起來像這樣;

Child = React.createClass({ 
    render() { 
     return <div>{this.props.someProp}</div>; 
    } 
}); 

Parent = React.createClass({ 
    render() { 
     return <Child someProp={"an example value"}/>; 
    } 
}); 

掛載Parent現在將產生<div>an example value</div>被呈現到顯示器。

+0

謝謝,真的很感謝答案。但是,我已經在其他地方看到了這一點,並且無法將其與Lightbox-react小部件的語法以及其中包含的示例代碼(無法看到如何在示例代碼中添加道具)進行協調。當然,我錯過了明顯的。 (也請注意,道具必須能夠在初始渲染時進行更改 - 對於不同的視頻源,可能會多次調用燈箱 - 我認爲*如果我可以將道具作爲父狀態var傳遞,它將起作用自動?) – messy

+0

你在你的例子中寫它的方式非常好!值得注意的是,'React.createElement(VidPlayer,{vidSrc:this.state.myVidSrc})'與編寫'完全一樣,唯一的區別是您使用傳統的JS語法或更新的JSX語法。否則,它看起來像一個完全正常的反應代碼。另外,最初不要擔心昂貴的渲染。 React用於在後臺高效地緩存和重用組件。在你實際遇到問題之前,只要相信它就能做到這一點! – gravityplanx