Render Clappr player in ReactJS - reactjs

I'm using Clappr player with ReactJS.
I want Clappr player component appear and destroy when I click to a toggle button. But it seems like when Clappr player is created, the entire page has reload (the toggle button dissapear and appear in a blink). So here is my code:
ClapprComponent.js
import React, { Component } from 'react'
import Clappr from 'clappr'
class ClapprComponent extends Component {
shouldComponentUpdate(nextProps) {
let changed = (nextProps.source != this.props.source)
if (changed) {
this.change(nextProps.source)
}
return false
}
componentDidMount() {
this.change(this.props.source)
}
componentWillUnmount() {
this.destroyPlayer()
}
destroyPlayer = () => {
if (this.player) {
this.player.destroy()
}
this.player = null
}
change = source => {
if (this.player) {
this.player.load(source)
return
}
const { id, width, height } = this.props
this.player = new Clappr.Player({
baseUrl: "/assets/clappr",
parent: `#${id}`,
source: source,
autoPlay: true,
width: width,
height: height
})
}
render() {
const { id } = this.props
return (
<div id={id}></div>
)
}
}
export default ClapprComponent
Video.js
import React, { Component } from 'react'
import { Clappr } from '../components'
class VideoList extends Component {
constructor() {
super()
this.state = {
isActive: false
}
}
toggle() {
this.setState({
isActive: !this.state.isActive
})
}
render() {
const boxStyle = {
width: "640",
height: "360",
border: "2px solid",
margin: "0 auto"
}
return (
<div>
<div style={boxStyle}>
{this.state.isActive ?
<Clappr
id="video"
source="http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/sl.m3u8"
width="640"
height="360" />
: ''}
</div>
<button class="btn btn-primary" onClick={this.toggle.bind(this)}>Toggle</button>
</div>
)
}
}
export default VideoList
Anyone can explain why? And how to fix this problem?
Edit 1: I kind of understand why the button is reload. It's because in index.html <head>, I load some css. When the page is re-render, it load the css first, and then execute my app.min.js. The button doesn't reload in a blink if I move the css tags under the <script src="app.min.js"></script>.
But it doesn't solve my problem yet. Because the css files have to put in <head> tags. Any help? :(

Here you have a running (jsbin link) example. I simplified a little bit and it still shows your main requirement:
class ClapprComponent extends React.Component {
componentDidMount(){
const { id, source } = this.props;
this.clappr_player = new Clappr.Player({
parent: `#${id}`,
source: source
});
}
componentWillUnmount() {
this.clappr_player.destroy();
this.clappr_player = null;
}
render() {
const { id } = this.props;
return (
<div>
<p>Active</p>
<p id={id}></p>
</div>
);
}
}
class NotActive extends React.Component {
render() {
return (
<p>Not Active</p>
);
}
}
class App extends React.Component {
constructor(props){
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
isActive: false
}
}
toggle() {
this.setState({
isActive: !this.state.isActive
})
}
render() {
return (
<div>
<h1>Clappr React Demo</h1>
{ this.state.isActive ?
<ClapprComponent
id="video"
source="http://www.html5videoplayer.net/videos/toystory.mp4"
/> :
<NotActive />}
<button onClick={this.toggle}>Toggle</button>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
Also make sure to rename the button class property to className.
Maybe you can work from here to find your exact problem? Hope that helps.

In Clappr's documentation I found a like about how to use clappr with reactjs

Related

Changing state between two child class components in React

I have two class components: Title and PlayButton. By default, the Title is programmed to change images when it is being hovered over but I would like it so that when the Playbutton is hovered over, the Title also changes its image (changes the state of the image). How would I go about this? I know I should use a parent component that handles the state of both its "children" (the Title and the PlayButton), but since I'm new to react, I'm not sure how.
Any assistance would be appreciated, thank you!
Code for Title:
import React from 'react'
import './Title.css'
import playHoverProvider from './playHoverProvider'
class Title extends React.Component {
constructor(props) {
super(props);
this.state = {
imgSrc: require('./oglogo'),
control: require('./oglogo')
};
this.handleMouseOver = this.handleMouseOver.bind(this);
this.handleMouseOut = this.handleMouseOut.bind(this);
}
handleMouseOver() {
this.setState({
imgSrc: require('./difflogo')
});
}
handleMouseOut() {
this.setState({
imgSrc: require('./oglogo')
});
}
render() {
return (
<div className='logo'>
<view>
<img onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut} src={this.state.imgSrc}
style={{width: 800,
flex: 1,
height: null,
}}
alt = 'Logo' />
</view>
</div>
);
}
}
Title.propTypes = {
}
Title.defaultProps = {
}
export default Title;
Code for PlayButton:
import { hover } from '#testing-library/user-event/dist/hover';
import React from 'react'
import './PlayButton.css';
class PlayButton extends React.Component {
constructor(props) {
super(props);
this.state = {
imgSrc: require('./playbutton.png'),
disabled: false
};
this.handleMouseOver = this.handleMouseOver.bind(this);
this.handleMouseOut = this.handleMouseOut.bind(this);
}
// On-click
handleClick = (event) => {
if (this.state.disabled) {
return;
}
this.setState({
disabled: true
});
}
handleMouseOver () {
this.setState({
imgSrc: require('./playbuttonblue.png')
});
}
handleMouseOut () {
this.setState({
imgSrc: require('./playbutton.png')
});
}
render() {
return (
<div className='playbutton'>
<a href='./Rule'>
<button className='buttonprop' onClick={this.handleClick} disabled={this.state.disabled}>
{this.state.disabled ? '' :
<img onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
src={this.state.imgSrc} width = {100} height = {50} alt = 'Play'/>}
</button>
</a>
</div>
);
}
}
PlayButton.propTypes = {
}
PlayButton.defaultProps = {
}
export default PlayButton

Show a react-placeholder skeleton until a image loaded completely in a page

I'm Beginner in react, i want to show a skeleton placeholder until a image loads completely in my page so I used react-placeholder library for skeleton loader and set the loaded state to false so the skeleton loader shows.
I then change the loaded to true by setState it on onLoad function on img tag but my problem is the state is not changing so the skeleton loader shows infinitely thus hiding the image.
how to fix this? what i done wrong here? Someone please help me solve this.
import React from 'react';
import ReactPlaceholder from 'react-placeholder';
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
loaded: false
}
}
handleImageLoaded() {
this.setState({ loaded: true });
}
render() {
return (
<React.Fragment>
<ReactPlaceholder type = 'rect' ready = {this.state.loaded} style = {{height: 160}} >
<div className = "imageHolder" >
<img src ="http://someImage.png" alt = "" onLoad={this.handleImageLoaded.bind(this)} />
</div>
</ReactPlaceholder>
</React.Fragment>
)
}
}
"react-placeholder" is not rendering the image until state.loaded is true, so the onLoad callback will never be executed.
You should take the control of rendering the placeholder and control the image visibility by yourself, and do not use the "react-placeholder" component as it requires a children node, which is not the best election for this case.
import React, { Fragment } from "react";
import ImagePlaceholder from "./ImagePlaceholder";
class Image extends React.Component {
constructor(props) {
super(props);
this.state = {
loaded: false
}
}
handleImageLoaded() {
this.setState({ loaded: true });
}
render() {
const { loaded } = this.state;
const imageStyle = !loaded ? { display: "none" } : {};
return (
<div className = "imageHolder" >
{!loaded && <ImagePlaceholder/> }
<img src ="http://someImage.png" style={imageStyle} onLoad={this.handleImageLoaded.bind(this)} />
</div>
)
}
}
Anyway, if you still want to continue using "react-placeholder", then you could solve it with something like:
import React, { Fragment } from "react";
import ReactPlaceholder from "react-placeholder";
class Image extends React.Component {
constructor(props) {
super(props);
this.state = {
loaded: false
}
}
handleImageLoaded() {
this.setState({ loaded: true });
}
render() {
const { loaded } = this.state;
const imageStyle = !loaded ? { display: "none" } : {};
const image = <img src="http://someImage.png" style={imageStyle} onLoad={this.handleImageLoaded.bind(this)} />;
return (
<Fragment>
<ReactPlaceholder type="rect" ready={this.state.loaded} style={{height: 160}} >
<div className="imageHolder" >
{image}
</div>
</ReactPlaceholder>
{!loaded && image}
</Fragment>
)
}
}

ReactJS: Dragging element not working with onmousemove

Im trying to make my own implementation of a drag element by creating a wrapper component that will allow a subcomponent to be dragged. But for some reason, only the first wrapped element can be drag.
class DraggableElement extends Component {
draggable = false;
constructor()
{
super();
this.state = { transform: "translate(0px, 0px)" };
window.onmousemove = (e)=>{
this.log(`should component drag? = ${this.dragging}`);
if(this.dragging){
this.setState({
transform : `translate(${e.clientX}px, ${e.clientY}px)`
});
}
};
}
log(message){
console.log(`${this.props.id}: ${message}`);
}
onMouseDown(e){
this.dragging = true;
this.log(`is draggin? ${this.dragging}`);
}
onMouseUp(e){
this.dragging = false;
this.log("is not dragging");
}
render() {
return (
<div
className="draggable-element"
onMouseDown={(e)=> this.onMouseDown(e)}
onMouseUp={(e)=> this.onMouseUp(e)}
style={this.state}>
{this.props.children}
</div>
);
}
}
The Editor component, where I place all the draggable components:
// imports
import DraggableElement from './DraggableElement';
class Editor extends Component {
render() {
return (
<div>
<DraggableElement id="1">
<select></select>
</DraggableElement>
<DraggableElement id="2">
<select></select>
</DraggableElement>
</div>
);
}
}
And here the css for the 'dragglable-element':
.draggable-element{
border:solid 10px blue;
position:absolute;
display: inline-block;
}
And the App.js:
function App() {
return (
<div className="App">
<Editor></Editor>
</div>
);
}
Ok, i found the error. I should have used window.addEventListener instead of window.onmousemove since i was overriding the previous assingment of the callback.
I changed:
window.onmousemove = (e)=>{
this.log(`should component drag? = ${this.dragging}`);
if(this.dragging){
this.setState({
transform : `translate(${e.clientX}px, ${e.clientY}px)`
});
}
};
To:
window.addEventListener("mousemove",(e=>{
this.log(`show component drag? = ${this.dragging}`);
if(this.dragging){
this.setState({
transform : `translate(${e.clientX}px, ${e.clientY}px)`
});
}
e.preventDefault();
}));
And its working now.

Show a Simple Animation on setState in react

I display a data from JSON file to the DIV in my component.
I Set timeout for few seconds and after that the data displays.
I want to show a simple animation when the state changes to true.
Here is a sample of my Code Structure:
import someData from "../Data";
export default class Example extends Component {
constructor(props) {
super(props);
this.state = { contentLoad: false }
}
componentDidMount() {
setTimeout(() => {
this.setState({
contentLoad: true
})
}, 2500)
}
render() {
return (
<div>
{someData.map((someData) => {
return (
<div> {this.state.contentLoad && someData.name}</div>
)
})}
</div>
)
}
}
I read about react transition group, but cant understand cause i'm new to react. someone please use this as a template and provide me a codepen or codesandbox link for solution.
I agree with #JohnRuddell that Pose is a heavy library if all you need is a simple fade in. However I would look it if you are doing multiple animations that are more complex.
Sample code:
import React from "react";
import ReactDOM from "react-dom";
import posed from "react-pose";
import "./styles.css";
const AnimatedDiv = posed.div({
hidden: { opacity: 0 },
visible: { opacity: 1 }
});
class Example2 extends React.Component {
constructor(props) {
super(props);
this.state = { contentLoad: false };
}
componentDidMount() {
setTimeout(() => {
this.setState({
contentLoad: true
});
}, 2500);
}
someData = ["hello", "hi", "test"];
render() {
return (
<AnimatedDiv pose={this.state.contentLoad ? "visible" : "hidden"}>
{this.someData.map(t => {
return <div>{t}</div>;
})}
</AnimatedDiv>
);
}
}
ReactDOM.render(<Example2 />, document.getElementById("root"));
Sandbox link

React: TypeError: this._modal.$el.on is not a function

So I'm new to react and I'm trying to use a boilerplate but I'm getting the following error in the chrome console. Sorry if this is a repeat question but I've tried to google it and found nothing. Thanks for the help in advance.
(Console)
TypeError: this._modal.$el.on is not a function
(index.js)
import React from 'react'
import UIkit from 'uikit'
export default class Modal extends React.Component {
constructor(props) {
super(props)
}
componentDidMount() {
this._modal = UIkit.modal(this.refs.modal, {
container: false,
center: true
// stack: true
})
console.log(this._modal)
this._modal.$el.on('hide', () => {
this.props.onHide()
})
this._modal._callReady()
if(this.props.visible) {
this._modal.show()
}
}
componentWillReceiveProps(nextProps) {
const { visible } = nextProps
if(this.props.visible !== visible) {
if(visible) {
this._modal.show()
} else {
this._modal.hide()
}
}
}
render() {
return (
<div ref="modal">
{this.props.children}
</div>
)
}
}
It is recommended to handle your modal with your compoenent state and refs are usually used for DOM manipulation.
What you can do is to initialize your state:
constructor(props) {
super(props)
this.state= {
isOpen : false
}
}
in your componentWillReceiveProps:
componentWillReceiveProps(nextProps) {
const { visible } = nextProps
if(this.props.visible !== visible) {
this.setState({
isOpen: visible
})
}
}
and in your render method:
render() {
return (
<div ref="modal">
{this.state.isOpen && this.props.children}
</div>
)
}
Let me know if this issue still persists. Happy to help

Resources