react-photo-gallery don't change photos via state - reactjs

The photo object is not changing in the Gallery component via state.
I created a "folder gallery", a multi gallery component to render a new one if you select it by click.
See the demonstration:
https://codesandbox.io/s/50wr02n8q4
github issue:
https://github.com/neptunian/react-photo-gallery/issues/118
Envs:
react-photo-gallery: 6.2.2
react: 16.6.3
npm: 6.4.1
See the code below:
const folderPhotos = [
{
title: "Gallery one",
photos: [
{
src: "https://source.unsplash.com/2ShvY8Lf6l0/800x599"
},
{
src: "https://source.unsplash.com/Dm-qxdynoEc/800x799"
},
{
src: "https://source.unsplash.com/qDkso9nvCg0/600x799"
}
]
},
{
title: "Gallery two",
photos: [
{
src: "https://source.unsplash.com/iecJiKe_RNg/600x799"
},
{
src: "https://source.unsplash.com/epcsn8Ed8kY/600x799"
},
{
src: "https://source.unsplash.com/NQSWvyVRIJk/800x599"
}
]
}
];
The photoProps dimensions object:
const photoProps = {
width: 1,
height: 1
};
The internal component here:
<Gallery
columnsLength={6}
photosObj={folderPhotos}
photoProps={photoProps}
withLightbox={true}
/>
Now the Gallery component:
import _ from "lodash";
import React, { Component, Fragment } from "react";
import Gallery from "react-photo-gallery";
import Lightbox from "react-images";
export class PhotoGallery extends Component {
constructor(props) {
super(props);
// Bindables
this.showGallery = this.showGallery.bind(this);
this.openLightbox = this.openLightbox.bind(this);
this.closeLightbox = this.closeLightbox.bind(this);
this.goToPrevious = this.goToPrevious.bind(this);
this.goToNext = this.goToNext.bind(this);
}
state = {
photosObj: [],
currentImage: 0,
lightboxIsOpen: false
};
async showGallery(itemObj, photoProps) {
let photosObj = [];
if (!_.isEmpty(itemObj)) {
photosObj = await Object.keys(itemObj)
.map(i => itemObj[i])
.map(item => ({
...item,
width: photoProps.width,
height: photoProps.height
}));
this.setState({
photosObj
});
console.log("-- props: ", this.state.photosObj);
}
}
openLightbox(event, obj) {
this.setState({
currentImage: obj.index,
lightboxIsOpen: true
});
}
closeLightbox() {
this.setState({
currentImage: 0,
lightboxIsOpen: false
});
}
goToPrevious() {
this.setState({
currentImage: this.state.currentImage - 1
});
}
goToNext() {
this.setState({
currentImage: this.state.currentImage + 1
});
}
render() {
const { columnsLength, photosObj, photoProps, withLightbox } = this.props;
return (
<div className="section-body">
<div className="content-col-info">
<ul className="list-mentors w-list-unstyled">
{photosObj.map((itemObj, i) => (
<li key={i}>
<span
className="mentors-item w-inline-block"
onClick={() => this.showGallery(itemObj.photos, photoProps)}
>
<div>{itemObj.title}</div>
</span>
</li>
))}
</ul>
</div>
<div className="content-col-info">
{!_.isEmpty(this.state.photosObj) && (
<Gallery
columns={columnsLength}
photos={this.state.photosObj}
onClick={withLightbox ? this.openLightbox : null}
/>
)}
{!_.isEmpty(this.state.photosObj) && withLightbox && (
<Lightbox
images={this.state.photosObj}
onClose={this.closeLightbox}
onClickPrev={this.goToPrevious}
onClickNext={this.goToNext}
currentImage={this.state.currentImage}
isOpen={this.state.lightboxIsOpen}
/>
)}
</div>
</div>
);
}
}
export default PhotoGallery;
EDIT - I updated the Gallery props
I fix the Gallery component props of the example too.
loadGallery(columnsLength) {
import("./photo-gallery").then(Gallery => {
console.log("-- load gallery: ", this.state.photosObj);
return (
<Gallery.default
columnsLength={columnsLength}
photosObj={this.state.photosObj}
withLightbox={true}
/>
);
});
}
And to call this:
{!_.isEmpty(this.state.photosObj) && this.loadGallery(columnsLength)}
References:
Intro to Dynamic import() in Create React App
React images

Since photos option is required in Gallery.js (Library)
Gallery.propTypes = {
photos: _propTypes2.default.arrayOf(_Photo.photoPropType).isRequired,
direction: _propTypes2.default.string,
onClick: _propTypes2.default.func,
columns: _propTypes2.default.number,
margin: _propTypes2.default.number,
ImageComponent: _propTypes2.default.func
};
Pass "photos={this.state.photosObj}" in <Gallery /> of Gallery.js (your js file) as follows:
Code:
<Gallery
columnsLength={columnsLength}
photosObj={this.state.photosObj}
photos={this.state.photosObj}
withLightbox={true}
/>
I am not sure why you pass other options.

Related

change text of a specific button when clicked in React

I want to change the text of a specific button when I click on that button in React. But the issue is when I click the button the title will change for all buttons!
class Results extends Component {
constructor() {
super();
this.state = {
title: "Add to watchlist"
}
}
changeTitle = () => {
this.setState({ title: "Added" });
};
render() {
return (
<div className='results'>
{
this.props.movies.map((movie, index) => {
return (
<div className='card wrapper' key={index}>
<button className='watchListButton' onClick={this.changeTitle}>{this.state.title}</button>
</div>
)
})
}
</div>
)
}
}
You would need to come up with a mechanism to track added/removed titles per movie. For that, you would have to set your state properly. Example:
this.state = {
movies: [
{id: 1, title: 'Casino', added: false},
{id: 2, title: 'Goodfellas', added: false}
]
This way you can track what's added and what's not by passing the movie id to the function that marks movies as Added/Removed. I have put together this basic Sandbox for you to get you going in the right direction:
https://codesandbox.io/s/keen-moon-9dct9?file=/src/App.js
And here is the code for future reference:
import React, { Component } from "react";
import "./styles.css";
class App extends Component {
constructor() {
super();
this.state = {
movies: [
{ id: 1, title: "Casino", added: false },
{ id: 2, title: "Goodfellas", added: false }
]
};
}
changeTitle = (id) => {
this.setState(
this.state.movies.map((item) => {
if (item.id === id) item.added = !item.added;
return item;
})
);
};
render() {
const { movies } = this.state;
return (
<div className="results">
{movies.map((movie, index) => {
return (
<div className="card wrapper" key={index}>
{movie.title}
<button
className="watchListButton"
onClick={() => this.changeTitle(movie.id)}
>
{movie.added ? "Remove" : "Add"}
</button>
</div>
);
})}
</div>
);
}
}
export default App;

React Multi Carousel - Problem with customButtonGroup

I've been struggling with what seems like a simple solution for far too long. I'm new to typescript and new to react.
I'm trying to use the react-mulit-carousel NPM package.
I'm able to get the customButtonGroup to work successfully in the sandbox:
https://codesandbox.io/s/fervent-rain-332mn?file=/src/App.js:834-913
But when I try to implement that in my SPFX solution i get the following error:
Type '{}' is missing the following properties from type '{ [x: string]: any; next: any; previous: any; goToSlide: any; }': next, previous, goToSlide
import * as React from 'react';
import { IBrandsCarouselProps } from './IBrandsCarouselProps';
import { IBrandsCarouselState } from './IBrandsCarouselState';
import { IBrand } from './IBrand';
import styles from '../../../styles/styles.module.scss';
import { SPHttpClient } from '#microsoft/sp-http';
import Carousel from 'react-multi-carousel';
import 'react-multi-carousel/lib/styles.css';
import '../../../styles/react-carousel.scss';
import { getNextElement } from 'office-ui-fabric-react';
const responsive = {
desktop: {
breakpoint: { max: 4000, min: 768 },
items: 4,
partialVisibilityGutter: 0
},
tablet: {
breakpoint: { max: 768, min: 480 },
items: 3,
partialVisibilityGutter: 30
},
mobile: {
breakpoint: { max: 480, min: 0 },
items: 2,
partialVisibilityGutter: 30
}
};
export default class BrandsCarousel extends React.Component<IBrandsCarouselProps, IBrandsCarouselState>{
constructor(props) {
super(props);
this.state = {
displayedBrands: [],
isLoading: true
};
}
/**
* Loads data from a list by using a cached view
*/
public loadBrandsFromList(): Promise<IBrand[]> {
const queryUrlGetAllItems: string = `[[HIDDEN]]`;
return this.props.context.spHttpClient.get(
queryUrlGetAllItems,
SPHttpClient.configurations.v1)
.then(
(response: any) => {
if (response.status >= 200 && response.status < 300) {
return response.json();
} else {
return Promise.resolve(new Error(JSON.stringify(response)));
}
})
.then((data: any) => {
let documents: IBrand[] = [];
if (data) {
for (let i = 0; i < data.value.length; i++) {
let item = data.value[i];
var doc: IBrand = {
Title: item.Title,
Image: item.Image.Url ? item.Image.Url : "No Image Set",
Url: item.Url.Url,
Business: item.Business
};
documents.push(doc);
}
}
return documents;
}).catch((ex) => {
// console.log("readDocumentsFromLibrary > spHttpClient.get()...catch:", ex);
throw ex;
});
}
public render(): React.ReactElement<IBrandsCarouselProps> {
// Sorting is Done in the Rest Call
let items = this.state.displayedBrands;
// create a new list that filters by the tags
// Business is an array of strings
// If the item has an array value that matches the Props Business
if (this.props.Business != "All") {
let filteredItems = [];
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.Business.indexOf(this.props.Business) > -1) {
filteredItems.push(item);
}
}
items = filteredItems;
}
const ButtonGroup = ({ next, previous, goToSlide, ...rest }) => {
const {
carouselState: { currentSlide }
} = rest;
return (
<div className="carousel-button-group">
<div
className={currentSlide === 0 ? "disable" : ""}
onClick={() => previous()}
>
Prev
</div>
<div onClick={() => next()}>Next</div>
<div onClick={() => goToSlide(currentSlide + 1)}> Go to any slide </div>
</div>
);
};
return (
<div className={styles["brands-slider"] + " " + styles["card-docs-slider"] + " hub-carousel"}>
{this.props.IsTitle && this.props.Title != "" &&
<div className={styles["widget-header"]}>
<span className={styles["view"]}>{this.props.Title}</span>
</div>
}
<div className={styles["card-slider"]}>
{items && items.length > 0 &&
<Carousel
responsive={responsive}
arrows
additionalTransfrom={0}
itemClass={"react-carousel-item"}
minimumTouchDrag={80}
partialVisible
renderButtonGroupOutside
customButtonGroup={<ButtonGroup />}
>
{items.map((item) => {
return (
<a href={item.Url} className={styles["block-link"]} target="_blank">
<img src={item.Image} alt={item.Title} />
</a>
);
})
}
</Carousel>
}
{items && items.length == 0 &&
<p>No Brands found. Please, check the List</p>
}
</div>
</div>
);
}
public componentDidMount() {
this.loadBrandsFromList().then(
//resolve
(documents: IBrand[]) => {
this.setState({
displayedBrands: documents,
isLoading: false,
});
},
//reject
(data: any) => {
this.setState({
displayedBrands: [],
isLoading: false,
isErrorOccured: true,
errorMessage: data
});
}
).catch((ex) => {
this.setState({
displayedBrands: [],
isLoading: false,
isErrorOccured: true,
errorMessage: ex.errorMessage
});
});
}
}
Any help would be greatly appreciated. Thank you!
I was able to figure it out. I needed to pass parameters. Oops!
Hopefully this can help out another JSX, Typescript, React beginner in the future.
<Carousel
responsive={responsive}
arrows
additionalTransfrom={0}
itemClass={"react-carousel-item"}
minimumTouchDrag={80}
partialVisible
renderButtonGroupOutside
customButtonGroup={<ButtonGroup
next={this.props.next}
previous={this.props.previous}
rest={this.props.rest}
/>}
>
Here's the Custom Button group if it helps as well. I couldn't find the documentation to hide the next button.
const ButtonGroup = ({ next, previous, ...rest }) => {
const {
carouselState: { currentSlide, totalItems, slidesToShow }
} = rest;
return (
<div className="carousel-button-group">
<button aria-label="Go to previous slide"
className={currentSlide === 0 ? "disable" : "react-multiple-carousel__arrow react-multiple-carousel__arrow--left"}
onClick={() => previous()}></button>
<button aria-label="Go to next slide"
className={currentSlide === totalItems - slidesToShow ? "disable" : "react-multiple-carousel__arrow react-multiple-carousel__arrow--right"}
onClick={() => next()}></button>
</div>
);
};

Error: Objects are not valid as a React child (found: object with keys {id, name})

I'm encountering an issue while compiling my reactJS component:
import React, { Component } from "react";
class StatefullComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [
{ id: 1, name: "Perceuse" },
{ id: 2, name: "disqueuse" },
{ id: 3, name: "marteau" },
{ id: 4, name: "clé de 17" },
{ id: 5, name: "meuleuse" }
],
newItem: ""
};
this.addNewItemToState = this.addNewItemToState.bind(this);
this.handleChange = this.handleChange.bind(this);
this.removeThisItem = this.removeThisItem.bind(this);
}
sortItems() {
this.setState({
items: this.state.items.sort()
});
}
addNewItemToState() {
this.setState({
items: [...this.state.items, this.state.newItem],
newItem: ""
});
}
removeThisItem(bidule) {
const tmparray = this.state.items.filter(bazar => {
return bazar.id !== bidule;
});
console.log(tmparray);
this.setState({
items: tmparray
});
}
handleChange(e) {
this.setState({
newItem: e.target.value
});
}
render() {
return (
<div className="statefull">
<h2>Satefull component, build with a class</h2>
<ul>
{this.state.items.map(item => (
<li className="lambda">
{item}
<button onClick={this.removeThisItem(item.id)}>
supprimer cet item
</button>
</li>
))}
</ul>
<input
type="text"
placeholder="Ajouter un element"
value={this.state.newItem}
onChange={this.handleChange}
/>
<button onClick={this.addNewItemToState}>Ajouter</button>
</div>
);
}
}
export default StatefullComponent;
and my App.js:
import "./App.scss";
import React from "react";
import StatelessComponent from "./components/stateless-component";
import StatefullComponent from "./components/statefull-component";
function App() {
return (
<div className="App">
<StatefullComponent />
</div>
);
}
export default App;
Why do I get this error?
'Error: Objects are not valid as a React child (found: object with keys {id, name}). If you meant to render a collection of children, use an array instead.'
Did I badly formatted my items array in my state? It's important to me to have an id because I want to be able to delete an item.
Any clue? Thanks.
That's because you are trying to render an object in map. Change your ul to this:
<ul>
{
this.state.items.map((item, index) => <li className="lambda" key={index}>{item.name}<button onClick={this.removeThisItem(item.id)}>supprimer cet item</button></li>)
}
</ul>
Hope this works for you.
You need to display name using {item.name} but not using {item}. This is reason you get that error.
Also I noticed the following issues:
1-) You need to add a key property to li tag like this: <li className="lambda" key={item.id}>. React needs key property in a list.
2-) You need to change onClick={this.removeThisItem(item.id)} to <button onClick={() => this.removeThisItem(item.id)}>. You are calling the removeThisItem method, but it shouldn't be called.
import React, { Component } from "react";
class StatefullComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [
{ id: 1, name: "Perceuse" },
{ id: 2, name: "disqueuse" },
{ id: 3, name: "marteau" },
{ id: 4, name: "clé de 17" },
{ id: 5, name: "meuleuse" }
],
newItem: ""
};
this.addNewItemToState = this.addNewItemToState.bind(this);
this.handleChange = this.handleChange.bind(this);
this.removeThisItem = this.removeThisItem.bind(this);
}
sortItems() {
this.setState({
items: this.state.items.sort()
});
}
addNewItemToState() {
this.setState({
items: [...this.state.items, this.state.newItem],
newItem: ""
});
}
removeThisItem(bidule) {
const tmparray = this.state.items.filter(bazar => {
return bazar.id !== bidule;
});
console.log(tmparray);
this.setState({
items: tmparray
});
}
handleChange(e) {
this.setState({
newItem: e.target.value
});
}
render() {
return (
<div className="statefull">
<h2>Satefull component, build with a class</h2>
<ul>
{this.state.items.map(item => (
<li className="lambda" key={item.id}>
{item.name}
<button onClick={() => this.removeThisItem(item.id)}>
supprimer cet item
</button>
</li>
))}
</ul>
<input
type="text"
placeholder="Ajouter un element"
value={this.state.newItem}
onChange={this.handleChange}
/>
<button onClick={this.addNewItemToState}>Ajouter</button>
</div>
);
}
}
export default StatefullComponent;
Playground

Re render component React table

I am trying to re render a component. I have a refresh button and I want to clean all filters and sorting values when clicked.
The thing is that I can not make a re render, not even with forceUpdate(), it is doing NOTHING and I don't know why. Also, I tried with setState(), and nothing. What I want to happen is what happens when I change the page, it re renders the component. Please can anybody could help me? What am I doing wrong?
import React, { Component } from "react";
import DeleteComponent from "../components/DeleteComponent"
import ReactTable from 'react-table';
import { Link, withRouter } from 'react-router-dom';
import axios from "axios";
import { getJwt } from '../helpers/jwt'
import eye from '../img/eye.png'
import bin from '../img/bin.png'
import writing from '../img/writing.png'
class CustomReactTable extends Component {
constructor(props) {
super(props)
this.state = {
data: [],
showDelete: false,
item: null,
pages: null,
totalItems: null,
loading: false,
state: {},
}
}
fetchData = (state) => {
this.setState({ state: state })
const jwt = getJwt()
if (!jwt) {
this.props.history.push('/login')
}
let config = {
headers: { 'Authorization': `Bearer ${jwt}` },
params: {
page: state.page,
pageSize: state.pageSize,
sorted: state.sorted,
filtered: state.filtered
}
}
this.setState({ loading: true })
axios.get(`http://localhost:3001/api/v1${this.props.location.pathname}`, config)
.then(response => {
console.log(response)
this.setState({
data: response.data.result,
loading: false
})
})
axios.get(`http://localhost:3001/api/v1${this.props.location.pathname}/count-documents`, config)
.then(response => {
this.setState({
totalItems: response.data.result,
pages: Math.ceil(response.data.result / state.pageSize)
})
})
}
loadOptions = () => {
this.props.columns.push({
Header: "",
Cell: (row) => [
// Find a better way to add unique key
<Link to={`${this.props.location.pathname}/${row.original._id}/show`} key={row.original._id} params={{ id: row.original._id }}><button className="btn-xs btn-outline-light"><img style={{ width: '1em' }} src={eye} /></button></Link>,
<Link to={`${this.props.location.pathname}/${row.original._id}/edit`} key={row.original._id + 'a'}><button className="btn-xs btn-outline-light"><img style={{ width: '1em' }} src={writing} /></button></Link>,
<button key={row.original._id + 'b'} className="btn-xs btn-outline-light" onClick={() => { this.onClickDeleteButton(row.original._id) }}><img style={{ width: '1em' }} src={bin} /></button>
]
})
}
loadFunctionalities = () => {
return (
<div className='functionalities-react-table'>
<span className='functionalities-add-item-table'>
<Link to={`${this.props.location.pathname}/add`}><button className="btn-sm btn-outline-success">Add new {this.props.modelName}</button></Link>
</span>
<span className='functionalities-refresh-table'>
<button className="btn-sm btn-outline-dark">Refresh table</button>
</span>
</div>
)
}
onClickDeleteButton = (id) => {
this.setState({ showDelete: true, item: id })
}
onCancelDeleteClick = () => {
this.setState({ showDelete: false })
}
componentDidMount() {
this.loadOptions()
}
reloadData = () => {
this.fetchData(this.state.state)
}
render() {
return (
<div className='main-content'>
{this.state.showDelete && (
<DeleteComponent reloadData={this.reloadData} onCancelDeleteClick={this.onCancelDeleteClick} item={this.state.item} />
)}
<h3>{`${this.props.modelName} (${this.state.totalItems})`}</h3>
{this.loadFunctionalities()}
<ReactTable
data={this.state.data}
columns={this.props.columns}
manual
onFetchData={this.fetchData}
defaultPageSize={10}
pages={this.state.pages}
style={{ fontSize: '0.9em' }}
>
</ReactTable>
<div className="total-records-tag">{this.props.modelName}: {this.state.totalItems}</div>
</div >
)
}
}
export default withRouter(CustomReactTable);

How to play video in react

I have a play/pause button for every video.
When I click on the play button, the last video is always played, and the icon changes on all videos. I try to do that with refs and play() method but every time, whatever video the user selects just the last video is played. Every click event play the last one.
Also, the code for full screen does not work.
This is my code:
class Video extends React.Component {
constructor(props) {
super(props);
this.state = {
playing: false,
videoList: [
{
src: 'https://clips.vorwaerts-gmbh.de/VfE_html5.mp4',
type: "video/mp4"
},
{
src: "https://clips.vorwaerts-gmbh.de/VfE_html5.mp4",
type: "video/mp4"
},
{
src: "https://clips.vorwaerts-gmbh.de/VfE_html5.mp4",
type: "video/mp4"
},
{
src: "https://clips.vorwaerts-gmbh.de/VfE_html5.mp4",
type: "video/mp4"
}
]
}
}
onPlayPauseClick = (index) => (event) => {
this.setState({
playing: !this.state.playing
});
this.state.playing ? this.video.pause() : this.video.play();
}
// onFullScreenClick = (video) => {
// this.setState({ video: video })
// if (video.requestFullscreen) {
// video.requestFullscreen();
// } else if (video.webkitRequestFullscreen) {
// video.webkitRequestFullscreen();
// } else if (video.mozRequestFullscreen) {
// video.mozRequestFullscreen();
// } else if (video.msRequestFullscreen) {
// video.msRequestFullscreen();
// }
// }
renderList = () => {
const { playing } = this.state;
return this.state.videoList.map((item, index) => {
return (
<li key={`item_${index}`}>
<video ref={(video) => { this.video = video; }} src={item.src}></video>
<img
src={playing ? "https://icon2.kisspng.com/20180419/pyq/kisspng-computer-icons-arrow-triangle-play-icon-5ad83452103159.1624767815241186100663.jpg" : "https://cdn2.iconfinder.com/data/icons/flat-and-simple-pack-2/512/1_Control_pause-512.png"}
className="play"
onClick={this.onPlayPauseClick(index)}
/>
<img src="https://cdn3.iconfinder.com/data/icons/google-material-design-icons/48/ic_fullscreen_exit_48px-512.png" className="full" />
</li>
)
});
}
render() {
return (
<div>
<ul>
{this.renderList()}
</ul>
</div>
);
}
}
class Buttons extends React.Component {
render() {
return (
<div>
<Video />
</div>
);
}
}
ReactDOM.render(<Video />, document.getElementById('app'));
It's happened because you saved the last video item in this.video, after iterating through videoList array elements . Try to save ref in this['video_'+index]=video instead of this.video=video, and start to play with code this['video_'+index].play()
Hey I think you have your ref messed up, you can create a new array of ref and use it with the index
constructor () {
this.ref = [];
}
and in your return do something like this
return this.state.videoList.map((item, index) => {
return (
<li key={`item_${index}`}>
<video ref={(video) => { this.ref.push(video) }} src={item.src}></video>
<img
src={playing ? "https://icon2.kisspng.com/20180419/pyq/kisspng-computer-icons-arrow-triangle-play-icon-5ad83452103159.1624767815241186100663.jpg" : "https://cdn2.iconfinder.com/data/icons/flat-and-simple-pack-2/512/1_Control_pause-512.png"}
className="play"
onClick={this.onPlayPauseClick(index)}
/>
<img src="https://cdn3.iconfinder.com/data/icons/google-material-design-icons/48/ic_fullscreen_exit_48px-512.png" className="full" />
</li>
)
});
and then you can call your ref inside the play pause method
onPlayPauseClick = (index) => (event) => {
this.setState({
playing: !this.state.playing
});
this.state.playing ? this.ref[index].pause() : this.ref[index].play();
}
For fullscreen I can suggest you don't try to over complicate the things, there is an awesome library for the player you can go with it.
https://www.npmjs.com/package/react-player
Full functioning code for your question.
import React from "react";
class Video extends React.Component {
constructor(props) {
super(props);
this.video = [];
this.state = {
playing: [false, false, false, false],
videoList: [
{
src: "https://clips.vorwaerts-gmbh.de/VfE_html5.mp4",
type: "video/mp4"
},
{
src: "https://clips.vorwaerts-gmbh.de/VfE_html5.mp4",
type: "video/mp4"
},
{
src: "https://clips.vorwaerts-gmbh.de/VfE_html5.mp4",
type: "video/mp4"
},
{
src: "https://clips.vorwaerts-gmbh.de/VfE_html5.mp4",
type: "video/mp4"
}
]
};
}
onPlayPauseClick = index => event => {
this.setState(state => {
state.playing = !state.playing;
state.playing ? this.video[index].play() : this.video[index].pause();
return state.playing[index];
});
};
onFullScreenClick = index => event => {
let video = this.video[index];
if (video.requestFullscreen) {
video.requestFullscreen();
} else if (video.webkitRequestFullscreen) {
video.webkitRequestFullscreen();
} else if (video.mozRequestFullscreen) {
video.mozRequestFullscreen();
} else if (video.msRequestFullscreen) {
video.msRequestFullscreen();
}
};
renderList = () => {
const { playing } = this.state;
return this.state.videoList.map((item, index) => {
return (
<li key={`item_${index}`}>
<video
ref={video => {
this.video[index] = video;
}}
src={item.src}
/>
<img
src={
playing
? "https://icon2.kisspng.com/20180419/pyq/kisspng-computer-icons-arrow-triangle-play-icon-5ad83452103159.1624767815241186100663.jpg"
: "https://cdn2.iconfinder.com/data/icons/flat-and-simple-pack-2/512/1_Control_pause-512.png"
}
className="play"
onClick={this.onPlayPauseClick(index)}
/>
<img
src="https://cdn3.iconfinder.com/data/icons/google-material-design-icons/48/ic_fullscreen_exit_48px-512.png"
className="full"
onClick={this.onFullScreenClick(index)}
/>
</li>
);
});
};
render() {
return (
<div>
<ul>{this.renderList()}</ul>
</div>
);
}
}
export default Video;
Im use react-player, where option "controls" - Set to true or false to display native player controls. look at the "react-player", it has everything you need
<ReactPlayer url={'url/to/video'} className={classes.styleView} controls/>

Resources