Problem with customized video control in react - javascript

I am trying to add a play/pause control in my react project. Currently, I am using react-slick to build a carousel on my web. I have a problem with my customized button as shown below. I don't know why as I am pressing the button, the console logs the tag, but the video on my web didn't change its current status.
Here is part of my code:
const RootStyle = styled('div')(({ theme }) => ({
'& .slick-slide': {
float: theme.direction === 'rtl' ? 'right' : 'left',
'&:focus': { outline: 'none' },
},
}));
const videoElement = useRef(null);
const [playerState, setPlayerState] = useState({isPlaying: true});
const togglePlay = () => {
setPlayerState({
isPlaying: !playerState.isPlaying,
});
};
useEffect(() => {
playerState.isPlaying? videoElement.current.play() : videoElement.current.pause();
console.log(videoElement.current);
}, [playerState.isPlaying, videoElement]);
return (
<RootStyle >
<Box sx={{ p: 0 }} >
<Box sx={{ overflow: 'hidden', position: 'relative', border: '1px solid' }} >
<Slider {...settings1} asNavFor={nav2} ref={slider1} >
{data.map((url) => (
url.videoDurationSeconds != null &&
<Box position={'relative'}>
<video
key={url.id}
src={url.url}
ref={videoElement}
height={'100%'}
width={'100%'}
max-height={480}
max-width={870}
autoPlay
loop
muted
/>
<Typography {...styles}>
{url.videoDurationSeconds}
</Typography>
<button onClick={togglePlay} className='play-button' >
<BarChartRoundedIcon style={{color:'white'}} height={'100%'} width={'100%'}/>
</button>
</Box> ||
<LazyImage src={url.url} alt={url.id} height={480} width={870} loading="eager" objectFit="contain" />
))}
</Slider>
</Box>
</Box>
</RootStyle>
By the way, sometimes after I clicked the button several times, the console showed these, I don't know if this is related to my problem:
Error

Related

MUI : Out-of-range value `X` for the select component

I'm making a glossary where each of the definitions are a cards that can be flipped (CardFlip) I build an array where I send for each card, the data via props to my component "CardFlip" dealing with the actual construction of cards with my data
This is my first component sending everything :
<div>
{glossaire.map((carte, index) => (
<Fragment key={carte.dat_id}>
<CardFlip item={carte} tags={tags} />
</Fragment>
))}
</div>
First prop ,"item", contains information such as: a title, a definition, a search tag
Second prop, "tags", is the list of tags that a definition can have, a definition can have only one tag, right now only those tags are available : "Application", "Entreprise", "Technique" and "Télécom"
And here is the code for my second component (only the interesting part):
export default function CardFlip = ({ item, user, tags }) => {
// -- [Variables] --
// Flip front / back
const [isFlipped, setIsFlipped] = useState(false);
// Storage
const [titreDef, setTitreDef] = useState("");
const [definitionDef, setDefinitionDef] = useState("");
const [tagSelected, setTagSelected] = useState("");
// Flag for error
const [errorTitre, setErrorTitre] = useState(false);
const [errorDefinition, setErrorDefinition] = useState(false);
const [errorSelect, setErrorSelect] = useState(false);
console.log(item.dat_tag);
console.log(tags);
// -- [Handlers] --
// UPDATE
const handleTitre = (data) => {
setTitreDef(data);
setErrorTitre(false);
};
const handleDefinition = (data) => {
setDefinitionDef(data);
setErrorDefinition(false);
};
const handleSelect = (event) => {
const {
target: { value },
} = event;
setTagSelected(value);
setErrorSelect(false);
}
return (
<Grow in style={{ transformOrigin: "0 0 0" }} {...{ timeout: 1000 }}>
<div style={{ display: "flex", padding: "10px" }}>
<ReactCardFlip
isFlipped={isFlipped}
flipDirection="horizontal"
style={{ height: "100%" }}
>
<div
className={style.CardBack}
style={{ display: "flex", height: "100%" }}
>
<Card className={style.mainCard}>
<CardActions className={style.buttonFlipCard}>
<Tooltip title="Retour">
<IconButton
className={style.iconFlipCard}
disableRipple
onClick={() => setIsFlipped((prev) => !prev)}
>
<ChevronLeftIcon />
</IconButton>
</Tooltip>
</CardActions>
<CardContent>
<div className={style.divTagBack}>
<FormControl
sx={{width: "90%"}}
>
<InputLabel
id="SelectLabel"
sx={{display: "flex"}}
>
{<TagIcon />}
{" Tag"}
</InputLabel>
<Select
labelId="SelectLabel"
label={<TagIcon /> + " Tag"}
renderValue={(selected) => (
<Chip
onMouseDown={(event) => {
event.stopPropagation();
}}
key={selected}
label={selected}
icon={<TagIcon />}
/>
)}
defaultValue={item.dat_tag}
onChange={handleSelect}
>
{tags && tags.map((tag) => (
<MenuItem key={tag.dat_tag} value={tag.dat_tag}>
{tag.dat_tag}
</MenuItem>
))}
</Select>
</FormControl>
</div>
</CardContent>
</Card>
</div>
</ReactCardFlip>
</div>
</Grow>
);
};
When the user returns the card, he can change the title, description and tag of the chosen card.
My problem is with the Select.
In order to display the selected tag before any modification, I display the tag in defaultValue={item.dat_tag}
(Also tried with value and not defaultValue)
Then with my second prop, I build the list of my menu.
This is where I get my warning (which seems to extend the rendering time of the page considerably (Since it load / render like +100 definitions, getting a warning for every definition)
MUI: You have provided an out-of-range value Entreprise for the select component.
Consider providing a value that matches one of the available options or ''. The available values are "".
This is an example of what a console.logs told me about my props :
item.dat_tag
Entreprise
tags
0: {dat_tag: "Applicatif"}
1: {dat_tag: "Entreprise"}
2: {dat_tag: "Technique"}
3: {dat_tag: "Télécom"}
I already looked at several posts saying to put in a string variable my tag data (item.dat_tag) or to display my menu when it is not empty. No change.

React.js: How to add an item to the card?

I am learning react.js and trying to implement basic add to cart functionality trying to keep it simple, just to understand the flow.
I have two cards, in one of them are listed the items, and after selecting the item and clicking the button the corresponding item should appear in the another card.
As far as I understand I need to somehow filter and check if the unique property has a match with the parameter, add to the card.
Please, find the Codesandbox link and the code below
import Box from "#mui/material/Box";
import Button from "#mui/material/Button";
import Card from "#mui/material/Card";
import CardContent from "#mui/material/CardContent";
import { styled } from "#mui/material/styles";
import React, { useState, useEffect } from "react";
const StyledBox = styled("div")({
paddingRight: "70px",
paddingLeft: "70px",
boxShadow: "rgba(100, 100, 111, 0.2) 0px 7px 29px 0px",
backgroundColor: "#FFFFFF",
border: "1px solid black",
minHeight: "200px"
});
const AddToCard = () => {
const [data, setData] = useState([]);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((result) => setData(result))
.catch((e) => console.log(e));
}, []);
const addToCardHandleClick = (id) => {
setData(
data.map((item: any) => {
const tempItem = data.find((item: any) => item === id);
if (!tempItem) return [...item, { id }];
})
);
};
return (
<Card sx={{ maxWidth: 700, minHeight: "300px" }}>
<CardContent>
<Box
sx={{
display: "flex",
gap: "30px",
justifyContent: "center",
overflow: "auto"
}}
>
<StyledBox sx={{ minWidth: "100px" }}></StyledBox>//The selected item should appear here after clicking
<Box
sx={{
alignSelf: "center",
gap: "10px"
}}
>
<Button
variant="outlined"
onClick={() => addToCardHandleClick(null)} //instead of null should be correct property
>
Move
</Button>
</Box>
<StyledBox>
{data &&
data.map((item) => (
<ul key={item.id} style={{ listStyle: "none" }}>
<li>{item.name}</li>
</ul>
))}
</StyledBox>
</Box>
</CardContent>
</Card>
);
};
export default AddToCard;
Any help will be appreciated
I try it in the code sandbox: https://codesandbox.io/s/imgmediacard-material-demo-forked-9nq22
I use item.selected to keep track of clicked element and once you click on move I drop the item.selected property and add item.moved = true instead...
If you need to make the moved items appear in the right order, you can either:
Add item.order = ++counter or item.order = Date.now() and sort all item.moved by item.order
Use a separete array for moved items

How to toggle class when user selects a list item coming from api in react.s?

I'm working on an application where I render the DB results by a loop through using the map method.
When the user clicks on each item, first it will add those id's into an array and toggle a CSS class to change the border color of a particular selected item, when the item is selected again, the border will disappear, same goes for all items rendered in the UI. Adding the id's into an array is working fine.
I'm facing a problem toggling CSS style to change the border color when click on each item.
Here is my code to render items on DOM
const [selectedItems, setSelectedItems] = React.useState([])
const onClickHandler = (id) => {
if (selectedItems.indexOf(id) > -1) {
let updatedItems = selectedItems.filter(itemID => itemID !== id)
console.log(updatedItems);
setSelectedItems(updatedItems)
} else {
setSelectedItems(prevState => [...prevState, id] )
}
setOpen(true);
}
{
courses.length > 0 && courses.map(course => {
return (
<>
<CourseItem course={course} onClickHandler={onClickHandler} itemSelect={itemSelect} />
</>
)
})
}
function CourseItem({ course, onClickHandler }) {
const classes = useStyles();
return (
<>
<Col style={{ marginTop: 10 }}>
<Paper elevation={0} className={classes.card}>
<div className={classes.cardTop} style={{ backgroundImage: `url('${course.thumbnail}')`, backgroundSize: 'cover', backgroundPosition: 'center' }}>
<div style={{ padding: '8px 18px', display: 'flex', justifyContent : 'space-between' }}>
<CheckCircleIcon onClick={() => onClickHandler(course._id)} />
{/* <Typography component={"label"} variant="caption"> { course.level }</Typography> */}
<Chip label={course.level} style={{ color: '#000', backgroundColor: '#f9f9f9', fontFamily: 'regular1', position: 'relative', zIndex: 0}} variant="outlined" />
</div>
</div>
<div className={classes.cardBottom}>
<Typography> { course.moduleName }</Typography>
<Typography variant="subtitle2" component={"span"}> { course.description }</Typography>
</div>
</Paper>
</Col>
</>
)
}
You can use tow different class for two different condition. Then use clsx to conditionally apply class.
clsx link -> npm clsx

React Native, Image Slider Box with text

I'm new to react native and I installed react-native-image-slider-box but I also want that when image slide title of that image will also change like user slide image so title of that image will also change. I change code of react-native-image-slider-box package but it's not working.
Below is that Code
_renderItem({ item, index }) {
const {
ImageComponent,
ImageComponentStyle = {},
sliderBoxHeight,
disableOnPress,
resizeMethod,
resizeMode,
imageLoadingColor = "#E91E63"
} = this.props;
return (
<View
style={{
position: "relative",
justifyContent: "center"
}}
>
<Text style={[style.fontSize30Semi, {marginRight: moderateScale(100)}]}>
{this.props.title}
</Text> //that's the code I added in react-native-image-slider-box
<ImageComponent
style={[
{
width: '100%',
height: moderateScaleVertical(350),
marginVertical: moderateScaleVertical(10),
},
ImageComponentStyle
]}
source={typeof item === "string" ? { uri: item } : item}
resizeMethod={resizeMethod || "resize"}
resizeMode={resizeMode || "cover"}
onLoad={() => {}}
onLoadStart={() => {}}
onLoadEnd={() => {
let t = this.state.loading;
t[index] = true;
this.setState({ loading: t });
}}
{...this.props}
/>
{!this.state.loading[index] && (
<ActivityIndicator
size="large"
color={imageLoadingColor}
style={{
position: "absolute",
alignSelf: "center"
}}
/>
)}
</View>
);
}
Welcome.js
state = {
images: [imagePath.welcome1, imagePath.welcome2, imagePath.welcome3],
desc: ['Hello', 'My'],
};
...
<SliderBox images={this.state.images} title={this.state.desc} />
That's my code where I trying to render different title for different image. Can anyone please help me and tell how can I do that??
The library doenst support any texts, you can do something like below
state = {
images: [imagePath.welcome1, imagePath.welcome2, imagePath.welcome3],
desc: ['Hello', 'My'],
currentIndex:0
};
<Text>{this.state.desc[this.state.currentIndex]}</Text>
<SliderBox images={this.state.images} title={this.state.desc} currentImageEmitter={i=>this.setState({currentIndex:i})}/>
The currentImageEmitter will send the index of the current image and you can use it to update the state and show the text based on the index.

Is it possible to delay Fade's transition?

Goal: I want Fade's transition to happen after a certain time has passed (ex: 4000 milliseconds).
Here is a fragment of my code:
<Fade in timeout={{ enter: 8000 }}>
<Box display="flex" justifyContent="center">
<IconButton href="https://soundcloud.com/jyillamusic">
<Soundcloud />
</IconButton>
<IconButton href="https://www.instagram.com/justinyum98/">
<Instagram />
</IconButton>
</Box>
</Fade>
Expected result: With enter: 8000, I expect the transition to happen after 8000 milliseconds.
Actual result: The transition starts at 0 milliseconds, finishes after 8000 milliseconds.
Does Fade support delaying the Fade transition by some specified time?
(Looking at Fade's API, I assumed that duration.enteringScreen meant that it was the amount of milliseconds before the transition occurs, but I'm probably mistaken.)
In "Components > Transitions > Zoom demo" of Material UI doc there are some examples in order to achieve it; a bit more elegant than touch the state!
In esence, you can pass a style attribute to Fade component and set the delay (transitionDelay). In the code below we iterate a result array and causes each individual element be showed with a 100ms delay from previous.
{profileItems.map((pi, index) => (
<Fade in={profileItems.length > 0}
timeout={{ enter: 500, exit: 250 }}
style={{ transitionDelay: `${index * 100}ms` }}
key={`asi-${pi.key}-${index}`}>
<span>
<DisplayItem profileItem={pi} />
</span>
</Fade>))}
Fade does not implement a delay feature, however you can manually handle your transition status using in.
in
Show the component; triggers the enter or exit states
type: boolean
default: false
In code you could do :
<Fade in={this.state.in} timeout={{ enter: 8000 }}>
<Box display="flex" justifyContent="center">
<IconButton href="https://soundcloud.com/jyillamusic">
<Soundcloud />
</IconButton>
<IconButton href="https://www.instagram.com/justinyum98/">
<Instagram />
</IconButton>
</Box>
</Fade>
And on display run a timeout to wait and create the delay
this.state = {
in: false
};
setTimeout(() => {
setState({ in: true });
}, 8000);
To piggyback off of sebastienbarbier, you could create a custom transition component that will handle the state for you by simply passing a delay prop.
Here is what the component would look like (I added additional useful props):
const MyFade = ({
children,
in: In = true,
timeout = 1000,
delay = 0
}) => {
const [isIn, setIsIn] = useState(In && delay === 0)
useEffect(() => {
if (delay > 0) {
setTimeout(() => setIsIn(true), delay)
}
})
return (
<Fade in={isIn} timeout={timeout}>
{children}
</Fade>
)
}
And then for your specific issue to have it wait 4000ms:
<MyFade in timeout={{ enter: 8000 }} delay={4000}>
<Box display="flex" justifyContent="center">
<IconButton href="https://soundcloud.com/jyillamusic">
<Soundcloud />
</IconButton>
<IconButton href="https://www.instagram.com/justinyum98/">
<Instagram />
</IconButton>
</Box>
</MyFade>
This seem to work for me without Fade:
const [open, setOpen] = React.useState(false);
<List>
{[
'Inbox',
'Starred',
'Send email',
'Drafts',
'foo',
'bar',
'baz',
].map((text, index) => (
<ListItem
key={text}
sx={{
transitionProperty: 'all',
transitionDuration: '750ms',
...(open && {
opacity: 1,
transform: 'translateY(0)',
transitionDelay: `${index * 150}ms`,
}),
...(!open && {
opacity: 0,
transform: 'translateY(100%)',
}),
}}
>
or
<ListItem
key={text}
style={{ transitionDelay: open ? `${index * 150}ms` : '0ms' }}
>

Categories

Resources