React Multi Carousel - Problem with customButtonGroup - reactjs

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>
);
};

Related

Counters for each item in React.js

I know that some similar issues already have been posted here, but I cannot find the solution for my issue and here I am stuck with this code.
The problem is when I want to Increase or Decrease a counter, all other counters changes. Also I'm wondering were should I store the counter, should it be a unique variable or an array for each item.. ?
I'm having:
product_items.jsx
import React, { Component } from "react";
import Item from "./product_item";
class Items extends Component {
constructor(props) {
super(props);
this.state.unique = 0;
}
state = {
brands: [
{
id: 0,
name: "Water0",
price: "1.53",
{
id: 1,
name: "Water1",
price: "1.47",
},
{
id: 2,
name: "Water2",
price: "1.58",
},
{
id: 3,
name: "Water3",
price: "1.41",
category: "Still Water",
},
],
counter: 10,
counters: [
{ id: 1, value: 0 },
],
filterBrands: [],
};
componentDidMount() {
this.setState({
filterBrands: this.state.brands,
});
}
handleClick = (name) => {
let filterBrands = [];
if (name === "All") {
filterBrands = this.state.brands;
} else {
filterBrands = this.state.brands.filter(
(brands) => brands.category === name
);
}
this.setState({ filterBrands });
};
addToCart = (counter) => {
console.log("addToCart DONE");
this.setState(({ unique }) => ({
unique: unique + 1,
}));
};
handleIncrement = (counter) => {
// console.log(counter);
console.log("handleIncrement DONE");
const counters = [...this.state.counters];
const index = counters.indexOf(counter);
counters[index] = { ...counter };
counters[index].value++;
// this.setState({ counters });
// this.setState({ unique: this.state.unique + 1 });
// console.log(this.state.unique);
this.setState(({ unique }) => ({
unique: this.state.unique + 1,
}));
};
handleDecrease = (counter) => {
console.log("handleDecrease DONE");
const counters = [...this.state.counters];
const index = counters.indexOf(counter);
counters[index] = { ...counter };
counters[index].value--;
// this.setState({ counters });
// this.setState({ unique: this.state.unique - 1 });
this.setState(({ unique }) => ({
unique: this.state.unique - 1,
}));
};
render() {
return (
<div className="ctg-flex">
<div className="items">
{this.state.filterBrands.map((id, brands) => (
<Item
// key={id.key}
key={brands}
dataText={id.name}
dataPrice={id.price}
// counter_unique={this.state.counter_unique}
unique={this.state.unique}
// counter={this.state.counters.value}
counters={this.state.counters}
onClickaddToCart={this.addToCart}
onIncrement={this.handleIncrement}
onDecrease={this.handleDecrease}
/>
))}
</div>
</div>
);
}
}
export default Items;
product_item.jsx
import React, { Component } from "react";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import Counter from "./counter";
class Item extends Component {
render() {
return (
<Card >
<Card.Body>
<Card.Text>
this.props.unique : {this.props.unique}
// this.props.counters.value : {this.props.counters.value} //test isn't working
</Card.Text>
</Card.Body>
<Counter
// counters={counters}
counter={this.props.counter}
onIncrement={this.props.onIncrement}
onDecrease={this.props.onDecrease}
unique={this.props.unique}
/>
<Button
style={{
display: this.props.unique === 0 ? "block" : "none",
}}
onClick={() => this.props.onClickaddToCart(this.props.counter)}
>
ADD TO CART
</Button>
</Card>
);
}
}
export default Item;
and
counter.jsx
import React, { Component } from "react";
import Button from "react-bootstrap/Button";
class Counter extends Component {
render() {
return (
<div
style={{
display: this.props.unique === 0 ? "none" : "flex",
}}
>
<Button
onClick={() => this.props.onDecrease(this.props.counter)}
>
Decrease
</Button>
<span>
{this.props.unique} in cart
</span>
<Button
onClick={() => this.props.onIncrement(this.props.counter)}
>
Increase
</Button>
</div>
);
}
}
export default Counter;
Your counter should be an object whose key will be the id values of your products .
counter = {
[id1] : 0 , //initially 0
[id2] : 0
... and so on
}
then each time you increase the count get the id of the product and increase the counter
handleIncrement = (counter) => {
// get the id of the clicked product
const newCounter = { ... this.state.counter , [id] : counter[id]+1}
this.setState({counter : newCounter})
};
and get the counter value for each product object
this.state.counter[productId]
so final I get it, I merged product and counter in a single array to catch same single key in all array and use count properly.
product_items.jsx
state = {
brands: [
{
id: 0,
name: "Water0",
price: "1.53",
value: 0,
},
{
id: 1,
name: "Water1",
price: "1.17",
value: 0,
},
...
]
}
...
render() {
return (
<div >
{this.state.brands.map((item, key) => (
<Item
key={key}
item={item}
id={key}
onClickaddToCart={this.addToCart}
onIncrement={this.handleIncrement}
onDecrease={this.handleDecrease}
brands={this.state.brands}
/>
))}
</div>
);
}

How to render only 5 items in react autosuggest?

I'am using react autosuggest npm package to get the json data and display it. I want to display only 5 items. How to do it?
Form.js
import React from 'react'
import Autosuggest from 'react-autosuggest';
import cities from 'cities.json';
const getSuggestions = value => {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
// Here I get data from cities.json
return inputLength === 0 ? [] : cities.filter(lang =>
lang.name.toLowerCase().slice(0, inputLength) === inputValue
);
);
};
const getSuggestionValue = suggestion => suggestion.name;
const renderSuggestion = suggestion => (
<div>
{console.log('suggestion', suggestion)}
{suggestion.name}
</div>
);
class Form extends React.Component {
constructor() {
super();
this.state = {
value: '',
suggestions: []
};
}
onChange = (event, { newValue }) => {
this.setState({
value: newValue
});
};
onSuggestionsFetchRequested = ({ value }) => {
this.setState({
suggestions: getSuggestions(value)
});
};
onSuggestionsClearRequested = () => {
this.setState({
suggestions: []
});
};
render(){
const { value, suggestions } = this.state;
// Autosuggest will pass through all these props to the input.
const inputProps = {
placeholder: 'Search City...',
value,
onChange: this.onChange
};
return (
<div>
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
/>
<br/>
</div>
)
}
}
export default Form;
I want to render only 5 items, otherwise, computer hangs while loading huge data. Is there any other autocomplete react npm package, since I want only cities and country list. i.e when city is inputted, automatically the city name must be suggested with its relevant country.Any solution or suggestion highly appreciated. Thanks in advance
i modified you're getSuggestions() method a little i guess this should work for you.
const getSuggestions = value => {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
// Here I get data from cities.json
return inputLength === 0 ? [] : cities.filter(lang =>
lang.name.toLowerCase().slice(0, inputLength) === inputValue
).slice(0,5);
};
Use the Slice method with start index and last Index
suggestions={suggestions.slice(0, 5)}
import {
React
,Avatar
,axiosbase
} from '../../import-files';
import Autosuggest from 'react-autosuggest';
import './autosuggest.css';
import { withStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
import Paper from '#material-ui/core/Paper';
import MenuItem from '#material-ui/core/MenuItem';
let suggestions = [ { label: 'Afghanistan' } ];
function renderInputComponent(inputProps) {
const { classes, inputRef = () => {}, ref, ...other } = inputProps;
return (
<TextField
className={classes.textField}
fullWidth
variant="outlined"
InputProps={{
inputRef: node => {
ref(node);
inputRef(node);
},
classes: {
input: classes.input,
},
}}
{...other}
/>
);
}
function renderSuggestion(suggestion, { query, isHighlighted }) {
return (
<MenuItem selected={isHighlighted} component="div">
<div>
<strong key={String(suggestion.id)} style={{ fontWeight: 300 }}>
<span className="sugg-option">
<span className="icon-wrap">
<Avatar src={suggestion.Poster}></Avatar>
</span>
<span className="name">
{suggestion.Title}
</span>
</span>
</strong>
</div>
</MenuItem>
);
}
function initSuggestions(value) {
suggestions = value;
}
function getSuggestionValue(suggestion) {
return suggestion.Title;
}
function onSuggestionSelected(event, { suggestion, suggestionValue, suggestionIndex, sectionIndex, method }) {
console.log('HandleSuggestion() '+suggestionValue);
}
const styles = theme => ({
root: {
height: 50,
flexGrow: 1,
},
container: {
position: 'relative',
},
suggestionsContainerOpen: {
position: 'absolute',
zIndex: 998,
marginTop: theme.spacing.unit,
left: 0,
right: 0,
overflowY: 'scroll',
maxHeight:'376%'
},
suggestion: {
display: 'block',
},
suggestionsList: {
margin: 0,
padding: 0,
listStyleType: 'none',
},
divider: {
height: theme.spacing.unit * 2,
},
});
class IntegrationAutosuggest extends React.Component {
state = {
single: '',
popper: '',
suggestions: [],
};
componentDidMount() {
initSuggestions(suggestions);
}
// Filter logic
getSuggestions = async (value) => {
const inputValue = value.trim().toLowerCase();
var _filter = JSON.stringify({
filter : inputValue,
});
return await axiosbase.post(`${apiCall}`, _filter);
};
handleSuggestionsFetchRequested = ({ value }) => {
this.getSuggestions(value)
.then(data => {
if (data.Error) {
this.setState({
suggestions: []
});
} else {
const responseData = [];
data.data.itemsList.map((item, i) => {
let File = {
id: item.idEnc,
Title: item.englishFullName +' '+item.arabicFullName,
englishFullName: item.englishFullName,
arabicFullName: item.arabicFullName,
Poster: item.photoPath,
}
responseData.push(File);
});
this.setState({
suggestions: responseData
});
}
})
};
handleSuggestionsClearRequested = () => {
this.setState({
suggestions: [],
});
};
handleChange = name => (event, { newValue }) => {
this.setState({
[name]: newValue,
});
if(event.type=='click'){
if(typeof this.props.handleOrderUserFirstNameChange === "function"){
this.props.handleOrderUserFirstNameChange(newValue);
}
this.state.suggestions.filter(f=>f.Title===newValue).map((item, i) => {
//id
//Title
// Poster
if(typeof this.props.handleUserIDChange === "function"){
this.props.handleUserIDChange(item.id);
}
});
}
};
render() {
const { classes } = this.props;
// console.log('Re-render!!');
// console.log(this.props);
// console.log(this.state.suggestions);
const autosuggestProps = {
renderInputComponent,
suggestions: this.state.suggestions,
onSuggestionsFetchRequested: this.handleSuggestionsFetchRequested,
onSuggestionsClearRequested: this.handleSuggestionsClearRequested,
onSuggestionSelected: this.props.onSelect,
getSuggestionValue,
renderSuggestion,
};
return (
<div className={classes.root}>
<Autosuggest
{...autosuggestProps}
inputProps={{
classes,
placeholder: this.props.placeHolder,
value: this.state.single,
onChange: this.handleChange('single'),
}}
theme={{
container: classes.container,
suggestionsContainerOpen: classes.suggestionsContainerOpen,
suggestionsList: classes.suggestionsList,
suggestion: classes.suggestion,
}}
renderSuggestionsContainer={options => (
<Paper {...options.containerProps} square>
{options.children}
</Paper>
)}
/>
<div className={classes.divider} />
</div>
);
}
}
export default withStyles(styles)(IntegrationAutosuggest);

How to collect Switch value in React JS + Ant Design

I'm sorry for my basic knowledge and my basic english :)
My Question is: How to concenate switch value [I use Switch for each record in table]
This is the table
https://ibb.co/3TVLBK6
I've created table with one cell/field using Switch (On/Off)
And i want get the switch value when they are on
And here is the code
const columnsTableDepartmentModal = [
{
title: 'No',
dataIndex: 'no',
key: 'no',
},
{
title: 'Department',
dataIndex: 'department',
key: 'department',
},
{
title: 'Select',
dataIndex: 'select_department',
key: 'select_department',
render: (e, record) => (
<Switch
defaultChecked={e}
onChange={
(value) => onChangeSwitch(value,record)
}
checkedChildren="Yes"
unCheckedChildren="No"
/>
),
}];
This is what i now try
function onChangeSwitch(isSelect,record){
console.log(e); // True / False
console.log(record); // True / False
if(isSelect){
// push data to array
}
if(!isSelect){
// pop data from array
}
}
This is how i show the table
<Modal
title={modalDepartmentTitle}
visible={visibleDepartment}
width={800}
onOk={handleOkDepartment}
onCancel={handleCancelDepartment}
footer={[
<Button key="submit" type="primary" onClick={handleOkDepartment}>OK</Button>,
<Button key="button" type="danger" onClick={handleDeleteDepartment}>DELETE</Button>,
<Button key="back" onClick={handleCancelDepartment}>CANCEL</Button>,
]}
>
<Table
columns={columnsTableDepartmentModal}
dataSource={stateDepartment.data}
pagination={false}
scroll={{y: 325}}
/>
</Modal>
Expected result: 1,3,4
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import Switch from 'react-switch';
class App extends Component {
constructor() {
super();
this.state = {
checkedPos: [],
info: [],
};
}
componentWillMount()
{
let tmp = []
let pos = []
for (var i = 1; i < 6; i++) {
tmp.push("Info " + i)
pos.push(false);
}
this.setState({
info: tmp,
checkedPos: pos
})
}
handleChange(index, info)
{
if (!this.state.checkedPos[index])
{
this.setState(prev => ({
checkedPos: prev.checkedPos.map((val, i) => !val && i === index ? true : val),
}))
}
else if (this.state.checkedPos[index])
{
this.setState( prev => ({
checkedPos: prev.checkedPos.map((val, i) => val && i === index ? false : val),
}))
}
}
render() {
const listItems = this.state.info.map((item, index) =>
<div>
{item}
<Switch checked={this.state.checkedPos[index]}
onChange={ () => this.handleChange(index, this.state.info[index])}/>
{" Value is " + this.state.checkedPos[index]}
</div>
);
return (
<div>
{listItems}
</div>
);
}
}
render(<App />, document.getElementById('root'));
Demo here
Acording to #jose answer i've implemented to hook concept with this code
const [theArray, setTheArray] = useState([]);
const addEntry = useCallback((value) => {
setTheArray([...theArray, `${value}`]);
});
Then in function we can add value
function onChangeSwitch(isSelect,record){
console.log(isSelect); // True / False
console.log(record);
addEntry(record.no);
if(isSelect){
// push data to array
}
if(!isSelect){
// pop data from array
}
}
So when we display {enty}
<div key="adkfkdfkda">{theArray.map(entry =>
<span key={entry}>{entry},</span>
)}
</div>
We got value merged in string format
https://ibb.co/nQFK1C4
Thanks.

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/>

Cannot Find what is causing this : Warning: setState(...): Can only update a mounted or mounting component

So after looking over many different questions asking the about this warning, I have found that there is not one single reason why this would be occurring making it difficult to infer a solution on my own code.
So here is my code incase anyone has another pair of eyes they can put on it and spot maybe why i would be getting this error.
This error occurs when not on first arrival of the component but after leaving and returning to it again.
I have a smart container and a dumb component set up so here is the container:
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { listOrders, listUseCases } from '../../actions/order';
import { storeWithExpiration } from '../../utils/common.js';
import OrdersIndex from './OrdersIndex';
export class OrdersIndexContainer extends React.Component {
static propTypes = {
account: PropTypes.object.isRequired,
orders: PropTypes.object.isRequired,
platformMap: PropTypes.object.isRequired,
progress: PropTypes.number,
listOrdersAction: PropTypes.func.isRequired,
listUseCasesAction: PropTypes.func.isRequired,
};
render() {
const { orders, platformMap, progress } = this.props;
return (
<div>
<OrdersIndex
orders={ orders }
platformMap={ platformMap }
progress={ progress }
/>
</div>
);
}
renderOrderIndex = () => {
}
componentWillMount = () => {
const { account, listOrdersAction, listUseCasesAction } = this.props;
const token = storeWithExpiration.get('token');
listOrdersAction(token);
listUseCasesAction(account.id, token);
}
}
function mapStateToProps(state) {
const { account, orderList, progress } = state;
const orders = orderList.get('orders');
const platformMap = orderList.get('platformMap');
return { account, platformMap, orders, progress };
}
export default connect(mapStateToProps, {
listOrdersAction: listOrders,
listUseCasesAction: listUseCases,
})(OrdersIndexContainer);
And here is the dumb component:
import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import ReactDataGrid from 'react-data-grid';
import { Toolbar } from 'react-data-grid/addons';
import { Data } from 'react-data-grid/addons';
import moment from 'moment';
import { SIMPLE_DATE_FORMAT } from '../../config/app_config';
// import OrderWrapFormatter from './OrderWrapFormatter';
const TABLE_COLUMNS = [
{ key: 'cNumber', name: 'Customer #', width: 125 },
{ key: 'name', name: 'Name', width: 150 },
{ key: 'orderNumber', name: 'Order #', width: 90 },
{ key: 'platform', name: 'Platform' },
{ key: 'useCase', name: 'Use Case'/* , formatter: OrderWrapFormatter */ },
{ key: 'list', name: 'List' },
{ key: 'sku', name: 'SKU' },
{ key: 'startDate', name: 'Start Date' },
{ key: 'endDate', name: 'End Date' },
];
export default class OrdersIndex extends React.Component {
static propTypes = {
orders: PropTypes.object.isRequired,
platformMap: PropTypes.object.isRequired,
progress: PropTypes.number,
};
state = {
rows: [],
originalRows: [],
columns: TABLE_COLUMNS,
sortColumn: null,
sortDirection: null,
filters: {},
}
renderRows = (orders) => {
const _rows = [];
orders.map((o) => {
_rows.push({
key: o.order.id,
id: o.order.id,
cNumber: o.order.providerCustomerNumber,
name: o.order.company.name,
orderNumber: o.order.providerOrderNumber,
platform: o.platformUseCases[0].platform.description,
useCase: this.renderMulti(o.platformUseCases, 'useCase', 'description'),
list: this.renderMulti(o.listSKUs, 'dataSet', 'name'),
sku: this.renderMulti(o.listSKUs, 'fieldSet', 'name'),
startDate: moment(o.order.startDate).format(SIMPLE_DATE_FORMAT),
endDate: moment(o.order.endDate).format(SIMPLE_DATE_FORMAT),
});
return _rows;
});
return this.setState({
rows: _rows,
originalRows: _rows.slice(),
});
}
getRows = () => {
return Data.Selectors.getRows(this.state);
}
rowGetter = (rowIdx) => {
const rows = this.getRows();
return rows[rowIdx];
}
getSize = () => {
return this.getRows().length;
}
renderMulti = (multi, itemName, subItemName) => {
const objectArray = multi.map((object) => {
return object[itemName][subItemName];
});
return objectArray.join('\n');
}
handleGridSort = (sortColumn, sortDirection) => {
const { originalRows, rows } = this.state;
const comparer = (a, b) => {
if (sortDirection === 'ASC') {
return (a[sortColumn] > b[sortColumn]) ? 1 : -1;
}
else if (sortDirection === 'DESC') {
return (a[sortColumn] < b[sortColumn]) ? 1 : -1;
}
};
const newRows = sortDirection === 'NONE' ? originalRows.slice() : rows.sort(comparer);
this.setState({
rows: newRows,
});
}
handleRowUpdated = (e) => {
// merge updated row with current row and rerender by setting state
const { rows } = this.state;
Object.assign(rows[e.rowIdx], e.updated);
this.setState({
...rows,
});
}
handleFilterChange = (filter) => {
const { filters } = this.state;
const newFilters = Object.assign({}, filters);
if (filter.filterTerm) {
newFilters[filter.column.key] = filter;
}
else {
delete newFilters[filter.column.key];
}
this.setState({
filters: newFilters,
});
}
onClearFilters = () => {
// all filters removed
this.setState({
filters: {},
});
}
// Creates appropriate warnings to prevent entering
// the order form if the account is missing information
renderNotice = (message, buttonMessage, route) => {
return (
<div className="alert alert-warning">
<strong>Notice:</strong>
<p>{ message }</p>
<p>
<Link
to={ route }
className="btn btn-warning"
>
<i className='fa fa-plus'></i>
{ buttonMessage }
</Link>
</p>
</div>
);
}
render() {
const { platformMap, progress } = this.props;
const platformMessage = 'Your account is not associated with any platform use cases.' +
'You must select at least one use case before creating new orders.';
const platformButton = 'Add Use Cases';
const platformRoute = '/products';
return (
<div className="container">
<div className="row">
<div className="col-sm-12 col-md-8">
<h1>Orders</h1>
</div>
<div className="col-sm-12 col-md-4">
<span className="pull-right">
<Link
to="/orders/create/1"
className="btn btn-primary"
disabled
>
<i className='fa fa-plus'></i>Create New Order
</Link>
</span>
</div>
</div>
{ platformMap.size === 0 && progress === 0 ?
this.renderNotice(platformMessage, platformButton, platformRoute) : null }
<div className="row">
{ progress === 0 ?
<div className="col-md-12">
{ this.renderTable() }
</div> : null }
</div>
</div>
);
}
renderTable = () => {
const { orders } = this.props;
const { columns } = this.state;
return (
<div>
{ orders.size === 0 || orders === undefined ?
<p>Your account has no orders</p> :
<ReactDataGrid
onGridSort={ this.handleGridSort }
rowKey="key"
id="key"
columns={ columns }
rowGetter={ this.rowGetter }
rowsCount={ this.getSize() }
onRowUpdated={ this.handleRowUpdated }
toolbar={ <Toolbar enableFilter /> }
onAddFilter={ this.handleFilterChange }
onClearFilters={ this.onClearFilters }
minHeight={ 500 }
filterRowsButtonText="Search By Field"
/>
}
</div>
);
}
componentWillMount = () => {
const { orders } = this.props;
const columnArray =
TABLE_COLUMNS.map((c) => {
const copy = Object.assign({}, c);
copy.filterable = true;
copy.locked = true;
if (copy.key !== 'useCase') {
copy.sortable = true;
}
return copy;
});
this.setState({
columns: columnArray,
});
this.renderRows(orders);
}
componentWillReceiveProps = (nextProps) => {
const { orders } = nextProps;
if (orders.size > 0) {
this.renderRows(orders);
}
}
}
I understand this might be a lot but I cannot for the life of me determine what could be the cause. Thanks to anyone who takes a look.

Resources