How to add React components dynamically without reload?
Context
Newer to React; I have a parent component that is generating anywhere from 1-6 youtube videos, using react-youtube components. The Idea is that the YouTube
components will be generated dynamically based on youtube video ids in an array. Currently, I'm generating the components like
{this.state.videoIds.map((videoId, index) =>
<YouTube
key={index}
opts={opts}
videoId={videoId}
onReady={this._onReady} />
)}
As far as generating the components, it's working as expected. However, the issue is, when this.state.videoIds
gets updated, it causes all of the YouTube
components to be refreshed. That behavior makes sense to me.
Issue
The issue I have is the following: If the functionality stays the same, I need a way to be able to track each of the YouTube
components player time, so that if a refresh happens, I can pass that data back down to the components when they are refreshed so they are able to be played from where they left off.
So my question is, is there a way to dynamically generate these components without needing to refresh all of the existing components?
For what it's worth, I have thought about just having a parent component that will statically add the components for each use case, but that seems awfully clunky, and I don't really want to go that route.
Edit
This feels relevant, I'm divvying up the screen space evenly based on how many players are loaded at any given time, code looks like the following:
calculateVideoWidth = () => {
if (this.state.videoIds.length <= 3) {
return (document.body.clientWidth - 15) / this.state.videoIds.length;
} else {
return (document.body.clientWidth - 15) / this.MAX_NUMBER_OF_COLUMNS;
}
};
calculateVideoHeight = () => {
if (this.state.videoIds.length <= 3) {
return window.innerHeight - 4;
} else {
return (window.innerHeight - 4) / this.MAX_NUMBER_OF_ROWS;
}
};
In my render method, I'm doing the following:
let opts = {
height: this.calculateVideoHeight(),
width: this.calculateVideoWidth()
};
After looking at @Tholle's comment, it occurs to me that the 'reload' is coming from the resizing. Which I guess makes sense. There has to be a better way to do this?
Edit 1
Check out this link to see what I am experiencing: Video App. In the input box, just add a video id separated by a ','.
javascript reactjs youtube-iframe-api
|
show 1 more comment
Context
Newer to React; I have a parent component that is generating anywhere from 1-6 youtube videos, using react-youtube components. The Idea is that the YouTube
components will be generated dynamically based on youtube video ids in an array. Currently, I'm generating the components like
{this.state.videoIds.map((videoId, index) =>
<YouTube
key={index}
opts={opts}
videoId={videoId}
onReady={this._onReady} />
)}
As far as generating the components, it's working as expected. However, the issue is, when this.state.videoIds
gets updated, it causes all of the YouTube
components to be refreshed. That behavior makes sense to me.
Issue
The issue I have is the following: If the functionality stays the same, I need a way to be able to track each of the YouTube
components player time, so that if a refresh happens, I can pass that data back down to the components when they are refreshed so they are able to be played from where they left off.
So my question is, is there a way to dynamically generate these components without needing to refresh all of the existing components?
For what it's worth, I have thought about just having a parent component that will statically add the components for each use case, but that seems awfully clunky, and I don't really want to go that route.
Edit
This feels relevant, I'm divvying up the screen space evenly based on how many players are loaded at any given time, code looks like the following:
calculateVideoWidth = () => {
if (this.state.videoIds.length <= 3) {
return (document.body.clientWidth - 15) / this.state.videoIds.length;
} else {
return (document.body.clientWidth - 15) / this.MAX_NUMBER_OF_COLUMNS;
}
};
calculateVideoHeight = () => {
if (this.state.videoIds.length <= 3) {
return window.innerHeight - 4;
} else {
return (window.innerHeight - 4) / this.MAX_NUMBER_OF_ROWS;
}
};
In my render method, I'm doing the following:
let opts = {
height: this.calculateVideoHeight(),
width: this.calculateVideoWidth()
};
After looking at @Tholle's comment, it occurs to me that the 'reload' is coming from the resizing. Which I guess makes sense. There has to be a better way to do this?
Edit 1
Check out this link to see what I am experiencing: Video App. In the input box, just add a video id separated by a ','.
javascript reactjs youtube-iframe-api
How are you adding the new ids to thevideoIds
array? It doesn't seem to be refreshing in my simple example, but I might be misunderstanding you.
– Tholle
Nov 13 '18 at 17:17
1
Just throwing out an idea. Wrap<YouTube />
in another component extending PureComponent so that update only occurs when videoId of that component is updated?
– Sung Kim
Nov 13 '18 at 17:33
@Tholle, looks like the issue I'm having has to do more with the layout. Based on the number of players on the screen, I'm dividing up the visible screen space to the players evenly. In my render method, I have a function call for height and width. See my edits in the question.
– ndland
Nov 13 '18 at 17:44
I don't quite understand the layout you want to achieve, but can it not be achieved with CSS with e.g. Flexbox?
– Tholle
Nov 13 '18 at 18:09
I think a better approach would be to drop the hardcoded height and width and put the iframes in div containers and style those for a proper n-column layout. There are plenty of "responsive YouTube iframe" tutorials to be found on google such as this one google.dk/amp/s/benmarshall.me/responsive-iframes/amp
– Jonas Høgh
Nov 13 '18 at 18:12
|
show 1 more comment
Context
Newer to React; I have a parent component that is generating anywhere from 1-6 youtube videos, using react-youtube components. The Idea is that the YouTube
components will be generated dynamically based on youtube video ids in an array. Currently, I'm generating the components like
{this.state.videoIds.map((videoId, index) =>
<YouTube
key={index}
opts={opts}
videoId={videoId}
onReady={this._onReady} />
)}
As far as generating the components, it's working as expected. However, the issue is, when this.state.videoIds
gets updated, it causes all of the YouTube
components to be refreshed. That behavior makes sense to me.
Issue
The issue I have is the following: If the functionality stays the same, I need a way to be able to track each of the YouTube
components player time, so that if a refresh happens, I can pass that data back down to the components when they are refreshed so they are able to be played from where they left off.
So my question is, is there a way to dynamically generate these components without needing to refresh all of the existing components?
For what it's worth, I have thought about just having a parent component that will statically add the components for each use case, but that seems awfully clunky, and I don't really want to go that route.
Edit
This feels relevant, I'm divvying up the screen space evenly based on how many players are loaded at any given time, code looks like the following:
calculateVideoWidth = () => {
if (this.state.videoIds.length <= 3) {
return (document.body.clientWidth - 15) / this.state.videoIds.length;
} else {
return (document.body.clientWidth - 15) / this.MAX_NUMBER_OF_COLUMNS;
}
};
calculateVideoHeight = () => {
if (this.state.videoIds.length <= 3) {
return window.innerHeight - 4;
} else {
return (window.innerHeight - 4) / this.MAX_NUMBER_OF_ROWS;
}
};
In my render method, I'm doing the following:
let opts = {
height: this.calculateVideoHeight(),
width: this.calculateVideoWidth()
};
After looking at @Tholle's comment, it occurs to me that the 'reload' is coming from the resizing. Which I guess makes sense. There has to be a better way to do this?
Edit 1
Check out this link to see what I am experiencing: Video App. In the input box, just add a video id separated by a ','.
javascript reactjs youtube-iframe-api
Context
Newer to React; I have a parent component that is generating anywhere from 1-6 youtube videos, using react-youtube components. The Idea is that the YouTube
components will be generated dynamically based on youtube video ids in an array. Currently, I'm generating the components like
{this.state.videoIds.map((videoId, index) =>
<YouTube
key={index}
opts={opts}
videoId={videoId}
onReady={this._onReady} />
)}
As far as generating the components, it's working as expected. However, the issue is, when this.state.videoIds
gets updated, it causes all of the YouTube
components to be refreshed. That behavior makes sense to me.
Issue
The issue I have is the following: If the functionality stays the same, I need a way to be able to track each of the YouTube
components player time, so that if a refresh happens, I can pass that data back down to the components when they are refreshed so they are able to be played from where they left off.
So my question is, is there a way to dynamically generate these components without needing to refresh all of the existing components?
For what it's worth, I have thought about just having a parent component that will statically add the components for each use case, but that seems awfully clunky, and I don't really want to go that route.
Edit
This feels relevant, I'm divvying up the screen space evenly based on how many players are loaded at any given time, code looks like the following:
calculateVideoWidth = () => {
if (this.state.videoIds.length <= 3) {
return (document.body.clientWidth - 15) / this.state.videoIds.length;
} else {
return (document.body.clientWidth - 15) / this.MAX_NUMBER_OF_COLUMNS;
}
};
calculateVideoHeight = () => {
if (this.state.videoIds.length <= 3) {
return window.innerHeight - 4;
} else {
return (window.innerHeight - 4) / this.MAX_NUMBER_OF_ROWS;
}
};
In my render method, I'm doing the following:
let opts = {
height: this.calculateVideoHeight(),
width: this.calculateVideoWidth()
};
After looking at @Tholle's comment, it occurs to me that the 'reload' is coming from the resizing. Which I guess makes sense. There has to be a better way to do this?
Edit 1
Check out this link to see what I am experiencing: Video App. In the input box, just add a video id separated by a ','.
javascript reactjs youtube-iframe-api
javascript reactjs youtube-iframe-api
edited Nov 13 '18 at 17:57
ndland
asked Nov 13 '18 at 17:04
ndlandndland
1961314
1961314
How are you adding the new ids to thevideoIds
array? It doesn't seem to be refreshing in my simple example, but I might be misunderstanding you.
– Tholle
Nov 13 '18 at 17:17
1
Just throwing out an idea. Wrap<YouTube />
in another component extending PureComponent so that update only occurs when videoId of that component is updated?
– Sung Kim
Nov 13 '18 at 17:33
@Tholle, looks like the issue I'm having has to do more with the layout. Based on the number of players on the screen, I'm dividing up the visible screen space to the players evenly. In my render method, I have a function call for height and width. See my edits in the question.
– ndland
Nov 13 '18 at 17:44
I don't quite understand the layout you want to achieve, but can it not be achieved with CSS with e.g. Flexbox?
– Tholle
Nov 13 '18 at 18:09
I think a better approach would be to drop the hardcoded height and width and put the iframes in div containers and style those for a proper n-column layout. There are plenty of "responsive YouTube iframe" tutorials to be found on google such as this one google.dk/amp/s/benmarshall.me/responsive-iframes/amp
– Jonas Høgh
Nov 13 '18 at 18:12
|
show 1 more comment
How are you adding the new ids to thevideoIds
array? It doesn't seem to be refreshing in my simple example, but I might be misunderstanding you.
– Tholle
Nov 13 '18 at 17:17
1
Just throwing out an idea. Wrap<YouTube />
in another component extending PureComponent so that update only occurs when videoId of that component is updated?
– Sung Kim
Nov 13 '18 at 17:33
@Tholle, looks like the issue I'm having has to do more with the layout. Based on the number of players on the screen, I'm dividing up the visible screen space to the players evenly. In my render method, I have a function call for height and width. See my edits in the question.
– ndland
Nov 13 '18 at 17:44
I don't quite understand the layout you want to achieve, but can it not be achieved with CSS with e.g. Flexbox?
– Tholle
Nov 13 '18 at 18:09
I think a better approach would be to drop the hardcoded height and width and put the iframes in div containers and style those for a proper n-column layout. There are plenty of "responsive YouTube iframe" tutorials to be found on google such as this one google.dk/amp/s/benmarshall.me/responsive-iframes/amp
– Jonas Høgh
Nov 13 '18 at 18:12
How are you adding the new ids to the
videoIds
array? It doesn't seem to be refreshing in my simple example, but I might be misunderstanding you.– Tholle
Nov 13 '18 at 17:17
How are you adding the new ids to the
videoIds
array? It doesn't seem to be refreshing in my simple example, but I might be misunderstanding you.– Tholle
Nov 13 '18 at 17:17
1
1
Just throwing out an idea. Wrap
<YouTube />
in another component extending PureComponent so that update only occurs when videoId of that component is updated?– Sung Kim
Nov 13 '18 at 17:33
Just throwing out an idea. Wrap
<YouTube />
in another component extending PureComponent so that update only occurs when videoId of that component is updated?– Sung Kim
Nov 13 '18 at 17:33
@Tholle, looks like the issue I'm having has to do more with the layout. Based on the number of players on the screen, I'm dividing up the visible screen space to the players evenly. In my render method, I have a function call for height and width. See my edits in the question.
– ndland
Nov 13 '18 at 17:44
@Tholle, looks like the issue I'm having has to do more with the layout. Based on the number of players on the screen, I'm dividing up the visible screen space to the players evenly. In my render method, I have a function call for height and width. See my edits in the question.
– ndland
Nov 13 '18 at 17:44
I don't quite understand the layout you want to achieve, but can it not be achieved with CSS with e.g. Flexbox?
– Tholle
Nov 13 '18 at 18:09
I don't quite understand the layout you want to achieve, but can it not be achieved with CSS with e.g. Flexbox?
– Tholle
Nov 13 '18 at 18:09
I think a better approach would be to drop the hardcoded height and width and put the iframes in div containers and style those for a proper n-column layout. There are plenty of "responsive YouTube iframe" tutorials to be found on google such as this one google.dk/amp/s/benmarshall.me/responsive-iframes/amp
– Jonas Høgh
Nov 13 '18 at 18:12
I think a better approach would be to drop the hardcoded height and width and put the iframes in div containers and style those for a proper n-column layout. There are plenty of "responsive YouTube iframe" tutorials to be found on google such as this one google.dk/amp/s/benmarshall.me/responsive-iframes/amp
– Jonas Høgh
Nov 13 '18 at 18:12
|
show 1 more comment
2 Answers
2
active
oldest
votes
This code might help you to start video from wherever user left.
The thing is we need to maintain or store the last played state of video wherever user left, some where permanently not erasable on reload, so here implemented using localStorage
.
import React from "react";
import ReactDOM from "react-dom";
import YouTube from "react-`enter code here`youtube";
class App extends React.Component {
state = {
videoIds: ["2g811Eo7K8U"],
videosPlayState: {}
};
componentDidMount() {
let videosPlayState = localStorage.getItem("videosPlayState") || "{}";
this.setState({
videosPlayState: JSON.parse(videosPlayState)
});
}
addVideo = () => {
this.setState(prevState => ({
videoIds: [...prevState.videoIds, "9kBACkguBR0"]
}));
};
_onStateChange = (event, videoId) => {
let newPlayState = { ...this.state.videosPlayState
};
newPlayState[videoId] = event.target.getCurrentTime();
localStorage.setItem("videosPlayState", JSON.stringify(newPlayState));
};
_onReady(event, videoId) {
event.target.seekTo(this.state.videosPlayState[videoId] || 0);
}
render() {
const opts = {
height: "200",
width: "400",
playerVars: {
autoplay: 1
}
};
return ( <
div className = "App" >
<
div className = "video-container" > {
this.state.videoIds.map((videoId, index) => ( <
YouTube onStateChange = {
event => {
this._onStateChange(event, videoId);
}
}
onReady = {
event => {
this._onReady(event, videoId);
}
}
key = {
index
}
videoId = {
videoId
}
opts = {
opts
}
className = {
"item"
}
/>
))
} <
/div> <
div >
<
button onClick = {
this.addVideo
} > Add video < /button> <
/div> <
/div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render( < App / > , rootElement);
here is the css:
.video-container .item {
padding: 25px;
display: inline-block;
}
.video-container {
display: flex;
flex-wrap: wrap;
}
here is a link might help you enter link description here
add a comment |
After playing with flexbox a bit more, I was able to solve this issue. I ended up with the following:
html, body, #root, #root > div, div.container, iframe {
width: 100%;
height: 100%;
margin: 0;
}
div.container {
display: flex;
flex-wrap: wrap;
}
span {
flex-basis: 33%;
flex-grow: 1;
}
For reference, here is my jsx
<div>
<div className="container">
{this.state.videoIds.map((videoId, index) =>
<YouTube
id="flex-item"
key={index}
videoId={videoId}
onStateChange={this._onStateChange}
onReady={this._onReady}/>
)}
</div>
</div>
I figured this could be done with flexbox, but I hadn't come up with the solution for it yet. I hope this helps someone else out.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53286135%2fhow-to-add-react-components-dynamically-without-reload%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
This code might help you to start video from wherever user left.
The thing is we need to maintain or store the last played state of video wherever user left, some where permanently not erasable on reload, so here implemented using localStorage
.
import React from "react";
import ReactDOM from "react-dom";
import YouTube from "react-`enter code here`youtube";
class App extends React.Component {
state = {
videoIds: ["2g811Eo7K8U"],
videosPlayState: {}
};
componentDidMount() {
let videosPlayState = localStorage.getItem("videosPlayState") || "{}";
this.setState({
videosPlayState: JSON.parse(videosPlayState)
});
}
addVideo = () => {
this.setState(prevState => ({
videoIds: [...prevState.videoIds, "9kBACkguBR0"]
}));
};
_onStateChange = (event, videoId) => {
let newPlayState = { ...this.state.videosPlayState
};
newPlayState[videoId] = event.target.getCurrentTime();
localStorage.setItem("videosPlayState", JSON.stringify(newPlayState));
};
_onReady(event, videoId) {
event.target.seekTo(this.state.videosPlayState[videoId] || 0);
}
render() {
const opts = {
height: "200",
width: "400",
playerVars: {
autoplay: 1
}
};
return ( <
div className = "App" >
<
div className = "video-container" > {
this.state.videoIds.map((videoId, index) => ( <
YouTube onStateChange = {
event => {
this._onStateChange(event, videoId);
}
}
onReady = {
event => {
this._onReady(event, videoId);
}
}
key = {
index
}
videoId = {
videoId
}
opts = {
opts
}
className = {
"item"
}
/>
))
} <
/div> <
div >
<
button onClick = {
this.addVideo
} > Add video < /button> <
/div> <
/div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render( < App / > , rootElement);
here is the css:
.video-container .item {
padding: 25px;
display: inline-block;
}
.video-container {
display: flex;
flex-wrap: wrap;
}
here is a link might help you enter link description here
add a comment |
This code might help you to start video from wherever user left.
The thing is we need to maintain or store the last played state of video wherever user left, some where permanently not erasable on reload, so here implemented using localStorage
.
import React from "react";
import ReactDOM from "react-dom";
import YouTube from "react-`enter code here`youtube";
class App extends React.Component {
state = {
videoIds: ["2g811Eo7K8U"],
videosPlayState: {}
};
componentDidMount() {
let videosPlayState = localStorage.getItem("videosPlayState") || "{}";
this.setState({
videosPlayState: JSON.parse(videosPlayState)
});
}
addVideo = () => {
this.setState(prevState => ({
videoIds: [...prevState.videoIds, "9kBACkguBR0"]
}));
};
_onStateChange = (event, videoId) => {
let newPlayState = { ...this.state.videosPlayState
};
newPlayState[videoId] = event.target.getCurrentTime();
localStorage.setItem("videosPlayState", JSON.stringify(newPlayState));
};
_onReady(event, videoId) {
event.target.seekTo(this.state.videosPlayState[videoId] || 0);
}
render() {
const opts = {
height: "200",
width: "400",
playerVars: {
autoplay: 1
}
};
return ( <
div className = "App" >
<
div className = "video-container" > {
this.state.videoIds.map((videoId, index) => ( <
YouTube onStateChange = {
event => {
this._onStateChange(event, videoId);
}
}
onReady = {
event => {
this._onReady(event, videoId);
}
}
key = {
index
}
videoId = {
videoId
}
opts = {
opts
}
className = {
"item"
}
/>
))
} <
/div> <
div >
<
button onClick = {
this.addVideo
} > Add video < /button> <
/div> <
/div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render( < App / > , rootElement);
here is the css:
.video-container .item {
padding: 25px;
display: inline-block;
}
.video-container {
display: flex;
flex-wrap: wrap;
}
here is a link might help you enter link description here
add a comment |
This code might help you to start video from wherever user left.
The thing is we need to maintain or store the last played state of video wherever user left, some where permanently not erasable on reload, so here implemented using localStorage
.
import React from "react";
import ReactDOM from "react-dom";
import YouTube from "react-`enter code here`youtube";
class App extends React.Component {
state = {
videoIds: ["2g811Eo7K8U"],
videosPlayState: {}
};
componentDidMount() {
let videosPlayState = localStorage.getItem("videosPlayState") || "{}";
this.setState({
videosPlayState: JSON.parse(videosPlayState)
});
}
addVideo = () => {
this.setState(prevState => ({
videoIds: [...prevState.videoIds, "9kBACkguBR0"]
}));
};
_onStateChange = (event, videoId) => {
let newPlayState = { ...this.state.videosPlayState
};
newPlayState[videoId] = event.target.getCurrentTime();
localStorage.setItem("videosPlayState", JSON.stringify(newPlayState));
};
_onReady(event, videoId) {
event.target.seekTo(this.state.videosPlayState[videoId] || 0);
}
render() {
const opts = {
height: "200",
width: "400",
playerVars: {
autoplay: 1
}
};
return ( <
div className = "App" >
<
div className = "video-container" > {
this.state.videoIds.map((videoId, index) => ( <
YouTube onStateChange = {
event => {
this._onStateChange(event, videoId);
}
}
onReady = {
event => {
this._onReady(event, videoId);
}
}
key = {
index
}
videoId = {
videoId
}
opts = {
opts
}
className = {
"item"
}
/>
))
} <
/div> <
div >
<
button onClick = {
this.addVideo
} > Add video < /button> <
/div> <
/div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render( < App / > , rootElement);
here is the css:
.video-container .item {
padding: 25px;
display: inline-block;
}
.video-container {
display: flex;
flex-wrap: wrap;
}
here is a link might help you enter link description here
This code might help you to start video from wherever user left.
The thing is we need to maintain or store the last played state of video wherever user left, some where permanently not erasable on reload, so here implemented using localStorage
.
import React from "react";
import ReactDOM from "react-dom";
import YouTube from "react-`enter code here`youtube";
class App extends React.Component {
state = {
videoIds: ["2g811Eo7K8U"],
videosPlayState: {}
};
componentDidMount() {
let videosPlayState = localStorage.getItem("videosPlayState") || "{}";
this.setState({
videosPlayState: JSON.parse(videosPlayState)
});
}
addVideo = () => {
this.setState(prevState => ({
videoIds: [...prevState.videoIds, "9kBACkguBR0"]
}));
};
_onStateChange = (event, videoId) => {
let newPlayState = { ...this.state.videosPlayState
};
newPlayState[videoId] = event.target.getCurrentTime();
localStorage.setItem("videosPlayState", JSON.stringify(newPlayState));
};
_onReady(event, videoId) {
event.target.seekTo(this.state.videosPlayState[videoId] || 0);
}
render() {
const opts = {
height: "200",
width: "400",
playerVars: {
autoplay: 1
}
};
return ( <
div className = "App" >
<
div className = "video-container" > {
this.state.videoIds.map((videoId, index) => ( <
YouTube onStateChange = {
event => {
this._onStateChange(event, videoId);
}
}
onReady = {
event => {
this._onReady(event, videoId);
}
}
key = {
index
}
videoId = {
videoId
}
opts = {
opts
}
className = {
"item"
}
/>
))
} <
/div> <
div >
<
button onClick = {
this.addVideo
} > Add video < /button> <
/div> <
/div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render( < App / > , rootElement);
here is the css:
.video-container .item {
padding: 25px;
display: inline-block;
}
.video-container {
display: flex;
flex-wrap: wrap;
}
here is a link might help you enter link description here
edited Nov 13 '18 at 19:35
answered Nov 13 '18 at 18:40
Jaisa RamJaisa Ram
22137
22137
add a comment |
add a comment |
After playing with flexbox a bit more, I was able to solve this issue. I ended up with the following:
html, body, #root, #root > div, div.container, iframe {
width: 100%;
height: 100%;
margin: 0;
}
div.container {
display: flex;
flex-wrap: wrap;
}
span {
flex-basis: 33%;
flex-grow: 1;
}
For reference, here is my jsx
<div>
<div className="container">
{this.state.videoIds.map((videoId, index) =>
<YouTube
id="flex-item"
key={index}
videoId={videoId}
onStateChange={this._onStateChange}
onReady={this._onReady}/>
)}
</div>
</div>
I figured this could be done with flexbox, but I hadn't come up with the solution for it yet. I hope this helps someone else out.
add a comment |
After playing with flexbox a bit more, I was able to solve this issue. I ended up with the following:
html, body, #root, #root > div, div.container, iframe {
width: 100%;
height: 100%;
margin: 0;
}
div.container {
display: flex;
flex-wrap: wrap;
}
span {
flex-basis: 33%;
flex-grow: 1;
}
For reference, here is my jsx
<div>
<div className="container">
{this.state.videoIds.map((videoId, index) =>
<YouTube
id="flex-item"
key={index}
videoId={videoId}
onStateChange={this._onStateChange}
onReady={this._onReady}/>
)}
</div>
</div>
I figured this could be done with flexbox, but I hadn't come up with the solution for it yet. I hope this helps someone else out.
add a comment |
After playing with flexbox a bit more, I was able to solve this issue. I ended up with the following:
html, body, #root, #root > div, div.container, iframe {
width: 100%;
height: 100%;
margin: 0;
}
div.container {
display: flex;
flex-wrap: wrap;
}
span {
flex-basis: 33%;
flex-grow: 1;
}
For reference, here is my jsx
<div>
<div className="container">
{this.state.videoIds.map((videoId, index) =>
<YouTube
id="flex-item"
key={index}
videoId={videoId}
onStateChange={this._onStateChange}
onReady={this._onReady}/>
)}
</div>
</div>
I figured this could be done with flexbox, but I hadn't come up with the solution for it yet. I hope this helps someone else out.
After playing with flexbox a bit more, I was able to solve this issue. I ended up with the following:
html, body, #root, #root > div, div.container, iframe {
width: 100%;
height: 100%;
margin: 0;
}
div.container {
display: flex;
flex-wrap: wrap;
}
span {
flex-basis: 33%;
flex-grow: 1;
}
For reference, here is my jsx
<div>
<div className="container">
{this.state.videoIds.map((videoId, index) =>
<YouTube
id="flex-item"
key={index}
videoId={videoId}
onStateChange={this._onStateChange}
onReady={this._onReady}/>
)}
</div>
</div>
I figured this could be done with flexbox, but I hadn't come up with the solution for it yet. I hope this helps someone else out.
answered Nov 15 '18 at 17:28
ndlandndland
1961314
1961314
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53286135%2fhow-to-add-react-components-dynamically-without-reload%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
How are you adding the new ids to the
videoIds
array? It doesn't seem to be refreshing in my simple example, but I might be misunderstanding you.– Tholle
Nov 13 '18 at 17:17
1
Just throwing out an idea. Wrap
<YouTube />
in another component extending PureComponent so that update only occurs when videoId of that component is updated?– Sung Kim
Nov 13 '18 at 17:33
@Tholle, looks like the issue I'm having has to do more with the layout. Based on the number of players on the screen, I'm dividing up the visible screen space to the players evenly. In my render method, I have a function call for height and width. See my edits in the question.
– ndland
Nov 13 '18 at 17:44
I don't quite understand the layout you want to achieve, but can it not be achieved with CSS with e.g. Flexbox?
– Tholle
Nov 13 '18 at 18:09
I think a better approach would be to drop the hardcoded height and width and put the iframes in div containers and style those for a proper n-column layout. There are plenty of "responsive YouTube iframe" tutorials to be found on google such as this one google.dk/amp/s/benmarshall.me/responsive-iframes/amp
– Jonas Høgh
Nov 13 '18 at 18:12