The react-player is playing video even when playing={false}. I'm using antd modal which is wrapped around my player.
when I close the modal state changes to false. Which is passed in react-player but the player keeps on playing in the background.
import React, { Component } from 'react'
import { Modal } from "antd";
import ReactPlayer from "react-player";
export class demo extends Component {
constructor(props) {
super(props);
this.state = {
isModalOpen: false,
};
}
ConfirmationModalhandleCancel = () => {
this.setState({ isModalOpen: false });
};
ConfirmationModalPlay = () => {
this.setState({ isModalOpen: true });
};
getVideo = () => {
console.log("Modal state",this.state.isModalOpen)
return (
<ReactPlayer
playing={this.state.isModalOpen}
className="introductionVideoLearningPlanPage"
controls={true}
url="https://www.youtube.com/watch?v=agi4geKb8v8"
/>
);
};
getIntroVideoModal = () => {
return (
<Modal
title={null}
footer={null}
visible={this.state.isModalOpen}
onCancel={this.ConfirmationModalhandleCancel}
width="fit-content"
bodyStyle={{ padding: '0' }}
>
{this.getVideo()}
</Modal>
)
}
render() {
return (
<div>
{this.getIntroVideoModal()}
</div>
)
}
}
export default demo
I have observed that the console.log("Modal state", this.state.isModalOpen) is consoling false when the modal closes but the player keeps on playing. react-player version: 2.6.2 and 2.9.0.
How do I stop playing the video once the modal closes?
Friend, you can go with Antd Modal itself, nothing wrong with that. To be able to stop the video playback when the Modal gets closed, you must pass the property
// add this property to your ant Modal
destroyOnClose={true}
to the Modal. This is an another workaround with which I achieved the expected behavior. Thanks
This issue is specific to antd modal. I tried reactstrap modal and it worked.
Related
Dumb React question: how to set focus on input after it displayed and why my code doesn't work? (Without display toggle it works.)
edit: What I expect: after click on a button, the input field appears (by removing .dnone class) and get a focus on it. (But it doesn't.)
My code:
import "./styles.css"; // with .dnone class with display:none
import React from 'react';
export default class App extends React.Component {
constructor(props) {
super(props);
this.input = React.createRef();
this.state = {
active: false
}
}
click = (e) => {
e.preventDefault();
this.setState({
active: true
});
this.input.current.focus();
}
render () {
return (
<div className="App">
<input type="text" ref={this.input} className={(this.state.active ? "" : "dnone")} />
<button type="button" onClick={(e) => this.click(e)}>click</button>
</div>
);
}
}
live demo: https://codesandbox.io/s/immutable-sea-9884z?file=/src/App.js:0-607
Thank you!
The issue is that React state updates are asynchronously processed, so in the click handler when you enqueue a state update you are immediately attempting to focus on the input, but since the active state hasn't updated yet you can't, the dnone classname hasn't been removed and input made visible yet.
Move the focus logic into the componentDidUpdate lifecycle method to "respond" to the active state updating.
componentDidUpdate(prevProps, prevState) {
if (prevState.active !== this.state.active && this.state.active) {
this.input.current.focus();
}
}
click = (e) => {
e.preventDefault();
this.setState({
active: true
});
}
How to add a button in infowindow with google-maps-react?
Hello, I'm writing a React app, I was having an issue with changing state inside the InfoWindow from google-maps-react, the solution above helped me get through that hurdle.
Right now however, I'm having an issue with wanting to edit the content inside my InfoWindowEx component. Using the method above I am able to change the state of a text box inside the InfoWindowEx, however, when I click on the text box and I type it will let me type 1 letter and then I will have to click the text box again if I want to type the next letter, etc. I think this issue has to do with state.
I don't know if there is a solution to this, I have been trying a lot of different things, but hopefully someone can help me know what is going on.
Here is my InfoWindowEx component:
<InfoWindowEx
key={currentInfoWindow.id}
id={currentInfoWindow.id}
marker={this.state.activeMarker}
visible={this.state.showingInfoWindow}
selectedPlace={this.state.selectedPlace}
onInfoWindowClose={this.onInfoWindowClose}
>
<div >
{infoWindowEditBoxes}
{infoWindowContent}
</div>
</InfoWindowEx>
the Edit boxes are rendering in conditional statements here are they:
if (this.state.editButton) {
infoWindowEditBoxes = (
<div>
<input key={this.props.marker} id="editedName" type="text" placeholder="New Bathroom Name" onChange={this.handleTextBoxState}></input>
<input key={this.props.marker} id="editedLocationName" type="text" placeholder="New Bathroom Location" onChange={this.handleTextBoxState}></input>
<button onClick={() => this.handleSubmitChangesButtonState()}>Submit Changes</button>
</div>
);
}
else {
infoWindowEditBoxes = null
}
and here is my state change function:
handleTextBoxState = (evt) => {
const stateToChange = {}
stateToChange[evt.target.id] = evt.target.value
this.setState(stateToChange)
console.log(stateToChange)
}
Thanks in advance!
I believe component state is getting updated properly in your example, apparently this behavior is related with InfoWindowEx component itself. The way how it is implemented, setState() causes to a re-render InfoWindow component which leads to losing input focus.
You could consider the following updated version of component which prevents re-rendering of info window if it has been already opened:
export default class InfoWindowEx extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false
};
this.infoWindowRef = React.createRef();
this.containerElement = document.createElement(`div`);
}
componentDidUpdate(prevProps) {
if (this.props.children !== prevProps.children) {
ReactDOM.render(
React.Children.only(this.props.children),
this.containerElement
);
this.infoWindowRef.current.infowindow.setContent(this.containerElement);
this.setState({
isOpen: true
});
}
}
shouldComponentUpdate(nextProps, nextState) {
if (this.state.isOpen) {
return this.props.marker.position.toString() !== nextProps.marker.position.toString();
}
return true;
}
infoWindowClose(){
this.setState({
isOpen: false
});
}
render() {
return <InfoWindow onClose={this.infoWindowClose.bind(this)} ref={this.infoWindowRef} {...this.props} />;
}
}
Demo
Is it possible to use react to show and hide an existing div element by id?
For example, I want use react to have this <div id="example">this is example</div> show and hide by button click and this element is not created by react.
First you need to understand React's philosophy. I strongly suggest you read the official React tutorial: https://reactjs.org/tutorial/tutorial.html.
In this case you would like to appear and disappear a div, this can be accomplished by changing internal state of a React Component. Then you need to create a function that is bound to the context of the instance of the Component.
For example:
class Example extends Component {
constructor(props) {
super(props);
this.state = {
open: true,
};
}
toggle() {
const { open } = this.state;
this.setState({
open: !open,
});
}
render() {
const { open } = this.state;
return (
<main>
<button onClick={this.toggle.bind(this)}>{open ? 'Hide' : 'Show'}</button>
{open && <div id="example"><h1>this is example</h1></div>}
</main>
);
}
}
Here's a codepen: https://codepen.io/anon/pen/PxWdZK?editors=1010
I have written a Nav component which renders react-md Drawer component. Two functions in this file control Drawer's visibility-
showDrawer = () => {
this.setState({ visible: true });
};
hideDrawer = () => {
this.setState({ visible: false });
};
This component is rendered at App level.
I have a page with Toolbar component. This toolbar has a menu button that should open the Drawer in Nav component.
class Catalog extends React.Component {
render() {
return (
<div>
<Toolbar themed fixed title="Catalog" nav={<Button icon onClick={this.showDrawer}>menu</Button>} />
....
How can I implement it in React?
You're close. Assuming we're just using plain-old React, you'll want to call the constructor function (which requires calling super as well), bind the 'this' context to the functions, define those functions and call them in the toolbar code you have below.
Assuming we're not involving Redux and using component state, you'll also want to set an initial state for your app (going with false for my example).
When I do this myself, I'll usually condense the functions into one 'toggle' function which you can do nicely with a ternary, checking the state to decide whether to open or close the nav.
Not sure if that fully answers your question, but hopefully it's a start.
All together, that looks something like this. (Note that the current implementation will only open the drawer and not close it):
export default class Catalog extends React.Component {
constructor(props) {
super(props);
this.hideDrawer = this.hideDrawer.bind(this);
this.showDrawer = this.showDrawer.bind(this);
this.getNavStyle = this.getNavStyle.bind(this);
this.state = { visible: false }
}
getNavStyle() {
return this.state.visible
? {
overflow: 'scroll',
width: '200px',
}
: {
overflow: 'visible',
letterSpacing: '2px',
width: '200px',
};
}
showDrawer = () => {
this.setState({ visible: true });
};
hideDrawer = () => {
this.setState({ visible: false });
};
render() {
return (
<div>
<Toolbar themed fixed title="Catalog"
nav={
<Button icon onClick={this.showDrawer}>
menu
</Button>}
/>
</div>
)
}
}
When submitting a form, I wish to show a small popup for 2.5 seconds if the server sends back a bad response.
The logic is fairly simple, however, I cannot figure out how to make this popup listen to a boolean somewhere in the state management(MobX in my case). I can get the content into the Popup just fine, however, the trigger is a button(and the content will show, if you click it) - But how do I make it listen to a boolean value somewhere?
Fairly simple class here:
import React from "react";
import { Popup, Button } from "semantic-ui-react";
import { inject } from "mobx-react";
const timeoutLength = 2500;
#inject("store")
export default class ErrorPopup extends React.Component {
state = {
isOpen: false
};
handleOpen = () => {
this.setState({
isOpen: true
});
this.timeout = setTimeout(() => {
this.setState({
isOpen: false
})
}, timeoutLength)
};
handleClose = () => {
this.setState({
isOpen: false
});
clearTimeout(this.timeout)
};
render () {
const errorContent = this.props.data;
if(errorContent){
return(
<Popup
trigger={<Button content='Open controlled popup' />}
content={errorContent}
on='click'
open={this.state.isOpen}
onClose={this.handleClose}
onOpen={this.handleOpen}
position='top center'
/>
)
}
}
}
However, the trigger value is a button which is rendered if this.props.data is present. But that's not the behavior I wish; I simply want the popup to render(and thus trigger) if this.props.data is there; alternatively, I can provide a true value with props if need be.
But how do I make this component trigger without it being a hover/button?
How about passing in the isOpen prop? Then you could add some logic onto the componentWillReceiveProps hook:
import React from "react";
import { Popup, Button } from "semantic-ui-react";
import { inject } from "mobx-react";
const timeoutLength = 2500;
#inject("store")
export default class ErrorPopup extends React.Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
}
};
//This is where you trigger your methods
componentWillReceiveProps(nextProps){
if(true === nextProps.isOpen){
this.handleOpen();
} else {
this.handleClose();
}
}
handleOpen = () => {
this.setState({
isOpen: true
});
this.timeout = setTimeout(() => {
//No need to repeat yourself - use the existing method here
this.handleClose();
}, timeoutLength)
};
handleClose = () => {
this.setState({
isOpen: false
});
clearTimeout(this.timeout)
};
render () {
const errorContent = this.props.data;
if(errorContent){
return(
<Popup
trigger={<Button content='Open controlled popup' />}
content={errorContent}
on='click'
open={this.state.isOpen}
position='top center'
/>
)
}
}
}
Without a need of handling delay - you could simply pass in the isOpen prop and that would do the trick.
And here what it could look like in your parent component's render:
let isOpen = this.state.isOpen;
<ErrorPopup isOpen={isOpen}/>
Set this value to control the popup, ideally, this should be a part of your parent component's state. Having a stateful component as a parent is important to make the popup re-rendered
Just use the property open as in the documentation. There is a separate example when popup is opened by default.