I have implemented a slider like property. Inside each slide, there is a video and its name. I am using [react-player][1] to display the video thumbnail. Once you click on any of the video a modal will get open and will play the video I have rendered the react-player is that the light property is always true. But it's not working once you click on the video that particular position of the slider loses the light property.
import React, { Component } from 'react'
import IndividualSlider from './IndividualSlider'
import ModalVideo from 'react-modal-video'
import { Modal, Button } from 'antd';
import ReactPlayer from 'react-player/youtube';
export class Experience extends Component {
constructor(){
super();
this.state={
Video:[
{
url:'https://www.youtube.com/embed/H2yCdBIpxGY',
name:'Recurssion'
},
{
url:'https://www.youtube.com/embed/s5YgyJcoUI4',
name:'Array'
},
{
url:'https://www.youtube.com/embed/_C4kMqEkGM0',
name:'DP'
},
{
url:'https://www.youtube.com/embed/VBnbYNksWTA',
name:'Graph'
},
{
url:'https://www.youtube.com/embed/M1q3Pzk2UXs',
name:'Trie'
}
],
modalIsOpen:false,
modalLink:""
}
this.left = this.left.bind(this);
this.right=this.right.bind(this);
this.modalPlay = this.modalPlay.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.handleOk = this.handleOk.bind(this);
}
handleOk = e => {
console.log(e);
this.setState({
modalIsOpen: false,
});
};
handleCancel = e => {
console.log(e);
this.setState({
modalIsOpen: false,
});
};
modalPlay=(link)=>{
this.setState({
modalIsOpen:true,
modalLink:link
})
}
right=()=>{
let arr = this.state.Video;
let temp = arr[0];
arr.shift();
arr.push(temp);
this.setState({
Video:arr
})
}
left=()=>{
let arr = this.state.Video;
let temp = arr[arr.length-1];
arr.pop();
arr.unshift(temp);
this.setState({
Video:arr
})
}
render() {
return (
<div className="ExperienceAClass">
<div className="OneWeekHeading">
<h2 className="OneWeekCaption">
Experience a class
</h2>
<hr className="MentorsCaptionUnderLine" align="center" width="50%"></hr>
</div>
<Modal
title=""
visible={this.state.modalIsOpen}
onOk={this.handleOk}
onCancel={this.handleCancel}
footer={null}
>
<ReactPlayer className="ModalVideo" url={this.state.modalLink}/>
</Modal>
<div className="EntireSliderWrapper">
<a class="prev" onClick={this.left}>
</a>
<div className="VideoSlider">
{this.state.Video.map((child,index)=>{
return <IndividualSlider modalPlay={this.modalPlay} url={child.url} name=
{child.name}/>
})
}
</div>
<a class="next" onClick={this.right}>
</a>
</div>
</div>
)
}
}
export default Experience
And the IndividualSlider component is as follows:
import React, { Component } from 'react'
import ReactPlayer from 'react-player/youtube';
export class IndividualSlider extends Component {
constructor(){
super();
this.state={
light:true
}
this.onClick=this.onClick.bind(this)
}
onClick=()=>{
let modalPlay=this.props.modalPlay;
modalPlay(this.props.url);
}
render() {
return (
<div className="VideoDetails fade">
<ReactPlayer className="YoutubeVideo" onClick={this.onClick} light =
{this.state.light} url={this.props.url}/>
<p>
{this.props.name}
</p>
</div>
)
}
}
export default IndividualSlider
In the above code, I have made the light prop to be always true. As the slide is clicked this component renders but the thumbnail property is not held.
Also, When the modal closes the video keeps on playing. How to deal with that?
As you can see the video which was played regain it's light={true} once slid but the position where it was when played doesn't imply light={true}
I believe the problem is that because you have two instances of React player, one has the light property passed to it and the other is not. Since you always want the light property to work, pass it as a prop set to true always.
The light property is working in the individual slider, because you are indeed setting it in the individual slider
// Inside IndividualSlider component you have this
<ReactPlayer className="YoutubeVideo" onClick={this.onClick} light =
{this.state.light} url={this.props.url}/>
// remove state it and make it like this, since state is not needed
<ReactPlayer className="YoutubeVideo" onClick={this.onClick} light={true} url={this.props.url}/>
Now you are losing the light when clicking on an individual video, because that video is rendered in the parent component (the Experience component_, and there you are not passing the light prop
// In Experience Component you have this
<ReactPlayer className="ModalVideo" url={this.state.modalLink} />
// change it to
<ReactPlayer className="ModalVideo" url={this.state.modalLink} light={true} />
Related
I have an array of videos which are displayed by Bootstrap carousel embedded in a modal dialog box. The video doesn't start playing automatically when the modal is show but you need to click on it and it will start playing. My issues is that on slide change the current video playing won't pause. So this is what i need to achieve, to pause current video when the user changes slides(back or forth). How can I do this?
BTW I am using React Js.
Any help is greatly valued.Thanks.✌️
Below is my Video Carousel component.
import React, { Component } from "react";
import 'bootstrap/dist/css/bootstrap.min.css';
import Carousel from 'react-bootstrap/Carousel';
import "../carousel.css";
export default class VideoCarousel extends Component {
constructor(props) {
super(props);
this.videoRef = React.createRef();
// this.state = {
// index: 0,
// isPlaying: false
// }
}
render(){
return(
<div>
<Carousel activeIndex={this.index} onSelect={this.handleChange} interval={null} className="carousel">
{this.props.items.map((item, index) => {
return (
<Carousel.Item key={index}>
<video
ref = {this.videoRef}
className="videoItem"
controls="controls"
>
<source src={item.src} type="video/mp4"/>
</video>
<Carousel.Caption>
{/* <h2>{item.title}</h2> */}
</Carousel.Caption>
</Carousel.Item>
);
})}
</Carousel>
</div>
)
}
}
Problem
You are using the same reference for all the items. After running the map function this.videoRef will be equal to the last element of the array.
Solution 1: keep the references in an array
Create the ref initialized by an empty array:
this.videoRef = React.createRef([]);
Iterate over the elements and assign the reference based on the index value:
<Carousel activeIndex={this.index} onSelect={this.handleChange} interval={null} className="carousel">
{this.props.items.map((item, index) => {
return (
<Carousel.Item key={index}>
<video
ref = {el => this.videoRef.current[index] = el}
...
>
...
</Carousel.Item>)
})}
</Carousel>
To pause the video use the element reference at specific position:
this.videoRef.current[index].pause();
Solution 2: Create a component for the carrousel item
You can handle the controls functions on componentDidMount/componentWillUnmount
this.videoRef = React.createRef(null);
Assign the reference:
export default class VideoCarouselItem extends Component {
constructor(props) {
super(props);
this.videoRef = React.createRef();
}
render(){
<Carousel.Item key={this.props.key}>
<video
ref = {this.videoRef}
...
>
</Carousel.Item>
}
}
Then through properties pass the info you need.
I am trying, to manipulate another element, by, passing props directly to it, and then have it display itself. If I pass true/false.
Live running code:
https://codesandbox.io/s/keen-dan-rt0kj
I don't know if it's possible to have a system of objects, and based on an event, tell a parent to display a child.
App.js
import React from "react";
import "./styles.css";
import Content from "./components/Content";
export default class App extends React.Component {
state = {
display: false
};
render() {
return (
<div className="App">
<button onClick={() => this.setState({ display: !this.state.display })}>
Display div
</button>
<Content display={this.state.display} />
</div>
);
}
}
./components/Content.js:
import React from "react";
export default class Content extends React.Component {
constructor(props) {
super();
this.state = {
display: props.display
};
}
render() {
const { display } = this.state;
return (
<div
id="mydiv"
className="mydiv"
style={{ display: display ? "block" : "none" }}
>
<h3>A simple div</h3>
</div>
);
}
}
Goal:
I want to based on a state, and based on fired event, display an element that already in store of root.
EDIT: I am aware that, this exists and can be used: import PropTypes from 'prop-types', however, I am not sure this is good practice, since it requires some parent or some other component to implement the props.
JUST Tried:
App:
<Content display={this.state.display} content={"Hello World"} />
Content:
<h3>{this.state.content}</h3>
It seems the passed in text, stored in Content state = {content: props.content} does get displayed, wheres, the boolean value does not work directly. Is there something wrong with sending in a bool ?
try this in your Content Component
export default class Content extends React.Component {
constructor(props) {
super();
this.state = {
};
}
render() {
return (
<>
{this.props.display?(
<div
id="mydiv"
className="mydiv"
>
<h3>A simple div</h3>
</div>
):null}
</>
);
}
}
The reason this may not be working is because you are initiating the state in a way that does not connect the display props after the component is initialized. This means that after the Content component is "constructed", the state of the Content and it's parent are not linked. This is because the constructor() function is only run once to initialize the state.
The best option you have is to not use the internal state of the Content component. Rather than initializing state with the display prop, just use the display prop in your render function.
Trying something like this might work
import React from "react";
export default class Content extends React.Component {
constructor(props) {
super(props);
}
render() {
const { display } = this.props;
return (
<div
id="mydiv"
className="mydiv"
style={{ display: display ? "block" : "none" }}
>
<h3>A simple div</h3>
</div>
);
}
}
Also I would reccommend using state in the root:
import React from "react";
import "./styles.css";
import Content from "./components/Content";
export default class App extends React.Component {
constructor(props) {
super();
state = {
display: false
};
}
render() {
return (
<div className="App">
<button onClick={() => this.setState({ display: !this.state.display })}>
Display div
</button>
<Content display={this.state.display} />
</div>
);
}
}
I use a component called "Modal" that I want to make global so I can use it in any other component. Modal will be used in all the components that need it.
My problem is that now the onclick {this.props.stateModal} in Widgets does not work and show nothing.
This is my Widgets.js
class Widgets extends Component {
render(){
return (
<aside className="widgets">
<div id="bq-datos">
<span>Todas tus campañas</span>
<a onClick={this.props.stateModal} className="content-datos orange" data-bq-datos="999"><div>Llamadas <span>ENTRANTES</span></div></a>
<a className="content-datos violet" data-bq-datos="854"><div>Llamadas <span>SALIENTES</span></div></a>
</div>
{
this.props.isModalOpen
? (
<Modal
stateModal = {this.props.stateModal}
isModalOpen={this.props.isModalOpen} >
<ModalWidgets/>
</Modal>
)
: null
}
<Comunicacion/>
</aside>
);
}
}
I need {this.props.stateModal} to work on my Modal component (in Modal.js)
This is my Modal.js with code for {this.props.stateModal} but not works.
import React, { Component } from 'react';
class Modal extends Component {
constructor(props) {
super(props);
this.state = {
isModalOpen: false,
};
this.stateModal = this.stateModal.bind(this);
}
stateModal() {
this.setState({
isModalOpen: !this.state.isModalOpen
});
alert('¡Ohhhh');
}
render(){
if(this.props.isOpen){
return (
<div id="modal">
{this.props.children}
<ModalWidgets/>
</div>
);
} else {
return null;
}
}
}
class ModalWidgets extends Component {
render(){
if(this.props.isModalOpen){
return(
<article id="md-descansos" className="medium">
hola tú!!
</article>
);
}
else{
return(
<div>k pasa!</div>
);
}
}
}
export default Modal;
I think that i need do something in my Modal.js but i don't know what it is
Edit:
I have changed the components to use Modal as the parent of all the other Modal that I want to use, such as ModalWidgets. But now when you click on the button of {this.props.stateModal} in Widgts not works.
Thanks!
You have to use stateModal function somewhere in your Modal component. Something like:
render(){
if(this.props.isOpen){
return (
<ModalGenerico>
<div id="modal">
<button type="button" onClick={this.stateModal}>Click here</button>
{this.props.children}
</div>
</ModalGenerico>
);
} else {
return <ModalGenerico />;
}
}
The button in the example above should be replaced with your backdrop of the modal (or anything else as you like).
Edited: You should take a look at this article State vs Props. Because I notice that you weren't clear the usage of them.
Besides, I don't think there's such thing called global component as you described. Every components in react are reusable and can be imported anywhere in the project.
As you can see this image, "+Las mor" is a "see more" button, which when clicked expands the whole paragraph written above.
I need React code for this to be functional. Any help will be appreciated.
I am also attaching the code upon which this functionality is to be applied.
<section id="section-2">
<h4>Om mig</h4>
<p className="para">
{about}
</p>
</section>
<p style={{color:'#d39176'}}>
<img src={plus1} />
Läs mer
</p>
You probably want a button that toggles the state of expanded text onClick. Upon hitting the button you would set the state to the opposite of what it was. Here's a working example I wrote with React and Reactstrap. I just tested it locally. Here's a video demo of what you will see: https://screencast.com/t/in5clDiyEcUs
import React, { Component } from 'react'
import { Container, Button } from 'reactstrap'
class App extends Component {
constructor(props) {
super(props)
this.state = {
expanded: false //begin with box closed
}
}
//function that takes in expanded and makes it the opposite of what it currently is
showButton = () => {
this.setState({ expanded: !this.state.expanded })
}
render() {
const { expanded } = this.state
return (
<Container style={ { justifyContent: 'center', alignItems: 'center' } }>
<div>Always visable text.</div>
<Button onClick={ this.showButton }>Expand</Button>
{
expanded && //show if expanded is true
<div>Extended Text Here</div>
}
</Container>
)
}
}
export default App
How to complete the border of circle based on selected option.
Here is four options.
1.Head
2.Body
3.Script
4.End Note
And I have a circle on side. What I am trying to do is, Head is by default active so circle border should be red color till 25% of its total area, then after selection of body it should be 50%. So on and at the end it should 100%.
Here is my code which I tried on click its changing text color till 4 clicks but I want above kind of thing.Being beginner in ReactJS I am unable to get this logic.
import React, { Component } from "react";
export default class Test extends Component {
constructor(props) {
super(props);
this.state = {
title: "Click here",
color:"red",
active:false,
clicks: 0,
}
}
getInitialState() {
return {
count: 0
};
}
changeTitle = () => {
this.setState((prevState) => ({
clicks: prevState.clicks + 1,
title: "New title",color:"green",active:true,
}));
};
render() {
return (
<div>
<div>count:{this.state.clicks}</div>
<h1 onClick={this.changeTitle.bind(this)} >Hello World </h1>
<h1 style={this.state.clicks===1 ? {color:"red"}:
(this.state.clicks===2)?{color:"yellow"}:
(this.state.clicks===2)?{color:"black"}:
{color:"green"}}>This is Magic: {this.state.title}</h1>;
</div>
)
}
}
Shoutout to #Ron for providing an answer in jquery (https://stackoverflow.com/a/50208291/7956790).
Use the css provided by #Ron.
Ok, here's the render function in React:
// your previous code
render() {
return (
<div id="circle-container">
<div className="quarter top-left">
<div className="quarter-fill top-left-fill" onClick={this.handleTopLeftClick}></div>
</div>
<div className="quarter top-right">
<div className="quarter-fill top-right-fill" onClick={this.handleTopRightClick}></div>
</div>
<div className="quarter bottom-left">
<div className="quarter-fill bottom-left-fill" onClick={this.handleBottomLeftClick}></div>
</div>
<div className="quarter bottom-right">
<div className="quarter-fill bottom-right-fill" onClick={this.handleBottomRightClick}></div>
</div>
</div>
);
}
Hook your onClick listeners to your arcs, e.g. onClick={this.handleTopRightClick} and bind them in the constructor function:
constructor(props) {
super(props);
this.handleTopLeftClick.bind(this);
this.handleTopRightClick.bind(this);
this.handleBottomLeftClick.bind(this);
this.handleBottomRightClick.bind(this);
}
And now define your handler functions in your class:
handleTopLeftClick() { }
handleTopRightClick() { }
handleBottomLeftClick() { }
handleBottomLeftClick() { }