How to use video.js with create-next-app nextjs? - css

I am trying to use Video.js with create-next-app, and I am not able to load the video.js.css. this is what my component looks like.
import videojs from 'video.js'
import videoStyles from '../node_modules/video.js/dist/video-js.min.css'
export default class VideoPlayer extends React.Component {
componentDidMount() {
// instantiate Video.js
this.player = videojs(this.videoNode, this.props, function onPlayerReady() {
console.log('onPlayerReady', this)
});
}
// destroy player on unmount
componentWillUnmount() {
if (this.player) {
this.player.dispose()
}
}
// wrap the player in a div with a `data-vjs-player` attribute
// so videojs won't create additional wrapper in the DOM
// see https://github.com/videojs/video.js/pull/3856
render() {
return (
<div>
<div data-vjs-player>
<video ref={ node => this.videoNode = node } className="video-js"></video>
</div>
<style jsx>{videoStyles}</style>
</div>
)
}
}
I am using styled-jsx/css loader to load the external css file.

Look at the next.js github example. It should be enough to get you started.

Related

how to fix css of video.js package in reacttjs

im using video.js in react for building video player but when im installing it using npm pacakage its does not provide its inbuilt css how i can add inbuilt css of video.js, instead of control bar im getting something like shown in picture below
import React, { Component } from 'react';
import videojs from 'video.js';
import { sendData } from '../../analytics/sendData';
class Video360Player extends Component {
componentDidMount() {
// instantiate Video.js
const videoJsOptions = {
autoplay: true,
controls: true,
sources: [{
src: this.props.videoUrl,
type: 'video/mp4'
}]
}
this.player = videojs(this.videoNode, videoJsOptions,this.props, function onPlayerReady() {
console.log('onPlayerReady', this)
});
}
// destroy player on unmount
componentWillUnmount() {
if (this.player) {
this.player.dispose()
}
}
// wrap the player in a div with a `data-vjs-player` attribute
// so videojs won't create additional wrapper in the DOM
// see https://github.com/videojs/video.js/pull/3856
render() {
return (
<div>
<div data-vjs-player>
<video ref={ node => this.videoNode = node } className="video-js"></video>
</div>
</div>
)
}}
export default Video360Player
Add the following line on top of component file:
import 'video.js/dist/video-js.css';
As pointed here: https://docs.videojs.com/tutorial-react.html
The reason your video is not playing is because the player is not ready. I ran into the same problem and the solution is explained in the documentation.
Basically, You must have a function to change the video source only when the player is ready.
const changePlayerOptions = () => {
// you can update the player through the Video.js player instance
if (!playerRef.current) {
return;
}
// [update player through instance's api]
playerRef.current.src([{ src: 'https://vjs.zencdn.net/v/oceans.mp4', type: 'video/mp4' }]);
};
It is explained in details here https://docs.videojs.com/tutorial-react.html

Importing css from a node module required in a plugin file with nuxt js

To add the fullscreen button to my leaflet map into nuxt i have installed leaflet.fullscreen package and i have edited my plugin leaflet.js like so:
import Vue from "vue";
import { LMap, LTileLayer, LMarker, LPolyline } from "vue2-leaflet";
require("leaflet-routing-machine");
require("lrm-graphhopper");
require("leaflet.fullscreen");
So i can use it in my main template:
<template>
<div>
<section class="search__page">
<div id="map-wrap" class="map__wrapper"></div>
</section>
</div>
</template>
<script>
import Tmap from "#/utils/TripMap.js";
export default {
mounted() {
this.initTmap();
},
data() {
return {
mainMap: null,
},
methods: {
initTmap() {
this.mainMap = new Tmap();
this.mainMap.load();
}
}
}
</script>
My class looks like that :
export default class Tmap {
constructor() {
this.map = null;
}
load) {
this.map = L.map("map-wrap", {
fullscreenControl: true,
fullscreenControlOptions: {
position: "topleft"
}).setView([46.7227062, 2.5046503], 6);
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
maxZoom: 18,
attribution: '© OpenStreetMap, ©TRIP'
}).addTo(this.map);
}
addMarkerOnClick() {
this.map.addEventListener("click", ev => {
L.marker(ev.latlng).addTo(this.map);
});
}
getBounds() {
return this.map.getBounds();
}
}
So in my main component i don't know how to import the css associated to this fullscreen plugin. I tried :
<style>
#import "~/node_modules/leaflet.fullscreen/Control.FullScreen.css";
</style>
That works but it's obviously not the good way to do that. Any idea how to that properly ?
From a quick web research i would say you should be able to access the styles like this:
#import "~leaflet/dist/leaflet.css";
When you register a global style in your nuxt.config.js the app will load it just once. I assume your build is taking more time than normal due to the node_modules path.
// nuxt.config.js
css: ['~/assets/styles/global.css'],
You could also give the nuxt resource loader a try.

How do I access css/scss with react?

I have a react component where I am trying to change the background color of the css when clicking the div.
I know you can set the color in the component, but I am using this component many times, and don't to make multiple component files with just a different color, and even if I did, I am curious besides the fact.
How can I access (or even console.log to figure it out on my own) the css file and its properties through the component? Thanks ahead of time.
If you want to keep all background-color styles in your .css/.scss file, you will need to have a good className strategy to link the styles to your components. Here is my suggestion:
styles.scss
.blue {
background-color: blue;
&.clicked {
background-color: red;
}
}
Container.js
import React from 'react';
import ClickableDiv from './ClickableDiv.js';
const Container = () => (
<ClickableDiv className="blue">
<p>This is my text.</p>
</ClickableDiv>
);
export default Container;
ClickableDiv.js
import React, { Component } from 'react';
class ClickableDiv extends Component {
constructor() {
super();
this.state = { clicked: false };
this.handleDivClick = this.handleDivClick.bind(this);
}
handleDivClick() {
this.setState({ clicked: true });
}
render() {
const divClassName = [this.props.classname];
if (this.state.clicked) divClassName.push('clicked');
return (
<div className={divClassName.join(' ').trim()} onClick={this.handleDivClick}>
{this.props.children}
</div>
);
}
}
export default ClickableDiv;
Rendered Markup
Unclicked:
<div class="blue"><p>This is my text.</p></div>
Clicked:
<div class="blue clicked"><p>This is my text.</p></div>
You can pass in the desired background color as a prop, and use internal state with an onClick handler.
Container.js
import React from 'react';
import ClickableDiv from './ClickableDiv';
const Container = () => (
<ClickableDiv backgroundColor="#FF0000">
<p>This is my text.</p>
</ClickableDiv>
);
export default Container;
ClickableDiv.js
import React, { Component } from 'react';
class ClickableDiv extends Component {
constructor() {
super();
this.state = {};
this.handleDivClick = this.handleDivClick.bind(this);
}
handleDivClick() {
const { backgroundColor } = this.props;
if (backgroundColor) this.setState({ backgroundColor });
}
render() {
const { backgroundColor } = this.state;
return (
<div style={{ backgroundColor }} onClick={this.handleDivClick}>
{this.props.children}
</div>
);
}
}
export default ClickableDiv;
Better to make an external css file and write your css code in that file and just import that one in index.html

Finding the width of an element when using React?

At which point in a React components life cycle can I get the components css properties which are set in a css file?
I've tried it in the render method and the componentDidMount method and neither assigned the css properties to the component.
export default class HomeArtist extends React.Component {
constructor(props){
super(props);
}
componentDidMount(){
let ImageStore = document.getElementsByClassName('home-artist-display');
console.log("ComponentDidMount: ", ImageStore);
}
render(){
var ImageStyle = {
backgroundImage: "url("+this.props.info.image+")"
};
return (
<div className="home-artist-display" style={ImageStyle}>
<Link to={"artist/" + this.props.info.id}>
<h3 className="home-artist-name">{this.props.info.name}</h3>
</Link>
</div>
)
}
}
I wrote a React library that exposes a size object (with width and height props) to components.
For your use case you could use it like so:
import SizeMe from 'react-sizeme'; // import me!
class HomeArtist extends React.Component {
...
render(){
// Size gets passed in as props!
const { width, height } = this.props.size;
var ImageStyle = {
backgroundImage: "url("+this.props.info.image+")"
};
return (
<div className="home-artist-display" style={ImageStyle}>
<Link to={"artist/" + this.props.info.id}>
<h3 className="home-artist-name">{this.props.info.name}</h3>
</Link>
</div>
)
}
}
// wrap your component export!
export default SizeMe()(HomeArtist);
--
You can find out full details at https://github.com/ctrlplusb/react-sizeme

How to change the behavior of Meteor accounts-ui so when a user logs in, the log out form automatically appears and vice versa

When a user logs in, I've tried adding a class to the 'logout form' that has a 'display: block' even with the '!important' tag which would override any display property on the logout form. I've tried reloading the page because that does bring up the logout form once a user logs in but it gets stuck in an infinite loop.
import React from 'react';
import ReactDOM from 'react-dom';
export default class AccountsUI extends React.Component {
componentDidMount() {
Accounts._loginButtonsSession.set('dropdownVisible', true);
this.view = Blaze.render(Template.loginButtons,
ReactDOM.findDOMNode(this.refs.container));
setTimeout(function () {
window.requestAnimationFrame(function() {
var node = ReactDOM.findDOMNode();
if (node !== undefined){
Accounts.onLogin(function(user){
document.getElementById('login-dropdown-list').className = "accounts-dialog hide-div"
console.log(document.getElementById('login-dropdown-list').className)
})
}
});
}, 250)
}
componentWillUnmount() {
Blaze.remove(this.view);
}
render() {
return <span ref="container" />
}
}
I'm also going to change how the class additions are triggered. I know that waiting 1/4 a second is very primitive and won't always work.
The Meteor.userId() function is reactive, which means if you call it in getMeteorData() it will be called again each time the userId changes. Save it to this.data, and use it in render().
I'd also suggest you create a React wrapper called LogoutUIWrapper for the Blaze component that only does wrapping and nothing else, just to make your life easier. See here: https://www.meteor.com/tutorials/react/adding-user-accounts
So you'll need to do something like this:
export default class AccountsUI extends React.Component {
getMeteorData() {
return {
userId: Meteor.userId(),
};
}
render() {
return (
<div>
{ this.data.userId ? null : <LogoutUIWrapper /> }
</div>
);
}
}
This way the LogoutUIWrapper component will only appear when the user is logged in.

Resources