react native videos in carousel - javascript

I have been trying to play single video from a slider containing of multiple videos and images..
What i used and tried is in below.
1. react-native-video, 2. react-native-snap-carousel
How to pause and play the videos wrapped in horizontal carousel and also which are in vertical FlatList Feeds
This is my carousel :
<View style={styles.sliderImgView}>
<Carousel
ref={(c) => { this._carousel = c; }}
data={chordData.images}
firstItem={0}
autoplay={autoPlay}
layout={layout}
loop={loop}
renderItem={this._renderItem}
onSnapToItem={(ind) => this.setState({ activeSlide: ind })}
loopClonesPerSide={bannersDataLength}
sliderWidth={SCREEN_WIDTH}
itemWidth={SCREEN_WIDTH} />
</View>
And my _renderItem is here :
if (item.mediaType === "image") {
return (
<View style={[styles.sliderImgView, GlobalStyles.ajCenter]} key={index}>
<Image source={{ uri: item.imgUrl }} resizeMode={"cover"} style={[styles.sliderImageStyle]} />
</View>
)
} else {
return (
<View style={[styles.sliderImgView, GlobalStyles.ajCenter]} key={index}>
<Video
source={{ uri: item.imgUrl }} // Can be a URL or a local file.
ref={(ref) => { this.player = ref }} // Store reference
resizeMode={"cover"}
paused={index !== this.state.activeSlide}
onLoad={this.onVideoLoad}
onError={this.onVideoError}
controls={false}
style={styles.backgroundVideo} />
</View>
)
}
And my Array look's like this :
result: [
{
id: 1,
title: "Feed Title",
description: "Feed description....",
data: [
{
id: 1,
mediaType: "image",
imgUrl: "https://images.unsplash.com/photo-1473177027534-53d906e9abcf?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1049&q=80"
},
{
id: 2,
mediaType: "video",
imgUrl: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
},
{
id: 3,
mediaType: "image",
imgUrl: "https://images.unsplash.com/photo-1473177027534-53d906e9abcf?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1049&q=80"
},
{
id: 4,
mediaType: "video",
imgUrl: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
},
]
},
{
id: 2,
title: "Feed Title",
description: "Feed description....",
data: [
{
id: 1,
mediaType: "image",
imgUrl: "https://images.unsplash.com/photo-1587269012604-b20cfbca7b16?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=849&q=80"
}
]
},
{
id: 3,
title: "Feed Title",
description: "Feed description....",
data: [
{
id: 1,
mediaType: "image",
imgUrl: "https://images.unsplash.com/photo-1473177027534-53d906e9abcf?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1049&q=80"
},
{
id: 2,
mediaType: "video",
imgUrl: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
},
]
},
{
id: 4,
title: "Feed Title",
description: "Feed description....",
data: [
{
id: 1,
mediaType: "image",
imgUrl: "https://images.unsplash.com/photo-1584679109597-c656b19974c9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80"
}
]
}
]
I don't want to show the player control that's why i hide it.. just like Instagram.
I don't know whether i should use this or not.
Present issue is: i should only play the video which is in visible section of user eyes which is in FlatList (i had't mention my flatList code as it is just list_design). i had scroll list with multiple objects with media data in arrays. how can i manage to stop playing id number 1 object of data array with id 2 or 4 active video index when other id number 3's media is in active.
I just want to achieve same as like Instagram post with no performance lagging issues.
can anyone please suggest or help me to achieve this.

Below did the magic controlling other feed's post media sliders to pause the video.
Add the below two props to your FlatList to get the current visible Index., and when ever the current visible index value changes update in componentDidUpdate and call your videoLoad method.
viewabilityConfig={{viewAreaCoveragePercentThreshold: 200}}
onViewableItemsChanged={this.onViewableItemsChanged}
onViewableItemsChanged = ({ viewableItems, changed }) => {
if (viewableItems && viewableItems.length > 0) {
this.setState({ currentVisibleIndex: viewableItems[0].index });
}
}
componentDidUpdate(prevProps, prevState){
if (prevProps.currentVisibleIndex !== this.props.currentVisibleIndex) {
this.setState({ currentVisibleIndex: this.props.currentVisibleIndex }, () => {
this.onVideoLoad();
})
//console.log("Check prevProps: " + prevProps.currentVisibleIndex + "----> Check pevState: " + prevState.currentVisibleIndex);
}
}

The best way to achieve this is using inviewport

For the above answer viewabilityConfig and onViewableItemsChanged
These props works for flatlist but react-native-snap-carousel the props (viewabilityConfig and onViewableItemsChanged) are not supported
As name of library suggest it might be only supported to images not video since it renders multiple time for loop

Related

Fetched object returns underfined

I have my data objects that I need to fetch, looking like this:
const products = {
one: {
id: 1,
name: 'One',
image: oneImage,
chair: {
name: 'ChairName',
image: myImage,
colors: {
white: {
name: 'White',
image: myImage,
},
black: {
name: 'Black',
image: myImage,
},
},
},
},
},
two: {
id: 2,
name: 'Two',
image: twoImage,
chair: {
name: 'Chair,
image: myImage,
colors: {
white: {
name: 'White',
image: myImage,
},
black: {
name: 'Black',
image: myImage,
},
},
},
},
};
I am fetching them with Object.value
const ProductsData = Object.values(products).map((data) => {
return (
<>
<div className="box" onClick={() => setSelectedData(data)}>
<img src={data.image} />
</div>
);
});
This code above works just fine, pointing out to selected data like this:
{selectedData ? (
<h1>{selectedData.name}</h1>
) : null}
But now I would like to map through the chair colors of selected Data, which causes errors.
What I tried to do was to just {selectedData.chair.colors.name}, which prints nothing and by console.log is underfined
How can I print selectedData of chair colors and how I can set the picked color as new selectedData? I am getting lost.
If you want to choose color, then you need to store it in another state variable.
const [selectedColor, setSelectedColor] = React.useState();
Use Object.values to iterate chair.colors
{Object.values(selectedData.chair.colors).map(val => {
return <div onClick={() => setSelectedColor(val.name)}>{val.name}</div>
})
}
Check this sandbox
You don't have selectedData.chair.colors.name, look again in your structure. There is selectedData.chair.colors.white.name or selectedData.chair.colors.black.name
colors is an object again. It does not have a property name. It has properties like white and black which are objects themselves.
Map through:
Object.values(selectedData.chair.colors)
let selectedChairColors = Object.values(selectedData.chair.colors)
;
console.log(selectedChairColors[0])
console.log(selectedChairColors[1])
You can log selectedChairColors to see that this will give you an array of values of colors property in chair of selectedData.
Looking at your sandbox it seems you are using no checks while running selectedData and hence the error. (Initially, selectedData is undefined).
This should work:
<div>{selectedData && Object.values(selectedData.chair.colors).map((x)=>
JSON.stringify(x)
)}</div>
Here is sandbox forked out of yours.

Is it possible to pass variable to antD Statistics component in React?

I'm trying to render data from a variable / function into an antD Statistic Component. It appears it can only take a raw string or number, but I need to pass data from props into it.
Is there a way around this? See code below - I would like to pass scenarios[0].investment into "Statistic title="Investment" value={scenarios[0].investment}" but it doesn't allow it. Current code below works AS-IS but breaks when I replace it with scenarios[0].investment
class RenderSummary extends Component {
state = {
clicked: false,
hovered: false,
};
hide = () => {
this.setState({
clicked: false,
hovered: false,
});
};
handleHoverChange = visible => {
this.setState({
hovered: visible,
clicked: false,
});
};
handleClickChange = visible => {
this.setState({
clicked: visible,
hovered: false,
});
};
render() {
const scenarios = this.props.scenarios;
const data = [
{
title: 'Title 1', content: <Statistic title="Investment" value={0}/>,
},
{
title: 'Title 2', content: <Statistic title="T Savings" value={0}/>,
},
{
title: 'Title 2', content: <Statistic title="E Savings" value={0}/>,
},
];
const hoverContent = <div>This is hover content.</div>;
const clickContent = <div>This is click content.</div>;
const onClick = () => console.log("Works!");
return(
<div className="container">
<div className="site-card-wrapper">
<Row gutter={16}>
<Col span={12}>
<Card title="User Scenario 1" bordered={true}>
<List
grid={{ gutter: 16, column: 3 }}
dataSource={data}
renderItem={item => (
<List.Item>
{item.content}
</List.Item>
)}
/>
</Card>
</Col>
</Row>
</div>
</div>
);
}
}
scenarios in props as follows
"scenarios : [0: {id: 0, investment: 0, tSavings: 0, eSavings: 0 …},1: {id: 0, investment: 1, tSavings: 1, eSavings: 1 …}]"
I think the way you have structured your scenarios array or the way you are passing it is incorrect.
An example of how you could pass scenarios to RenderSummary:
const App = () => {
const scenarios = [
{investment: 1}, // Add your other properties
{investment: 2},
{investment: 3},
]
return <RenderSummary scenarios={scenarios}/>
}
If you pass scenarios like above, you can pass it in the way you wanted to:
const data = [
{
title: "Title 1",
content: <Statistic title="Investment" value={scenarios[0].investment} />,
},
{
title: "Title 2",
content: <Statistic title="T Savings" value={scenarios[1].investment} />,
},
{
title: "Title 2",
content: <Statistic title="E Savings" value={scenarios[2].investment} />,
},
];

How to render the CloseIcon only when the image is inserted?

I am trying to create a form similar to google forms. Whenever a user inserts image I want to preview the image. Now, I have created a function updateImageLink to update the state once user inserts image. The function is below:
updateImageLink = (link, position) => {
let questions = [...this.state.questions];
let i = position.question;
if (position.option == null) {
questions[i].questionImage = link;
} else {
var j = position.option
questions[i].options[j].optionImage = link;
}
this.setState({ questions });
}
Suppose the user wants to delete the image so for that I have created a delete button and passed the function through onClick prop as follows:
<IconButton
style={{
marginLeft: "3px",
marginTop: "-15px",
zIndex: 999,
backgroundColor: "lightgrey",
color: "grey",
}}
size="small"
onClick={() => {
this.updateImageLink("", { question: i, option: null });
}}
>
<CloseIcon />
</IconButton>
Now, this code renders the CloseIcon even when there's no image. The problem is with binding the function. If I write:
onClick={this.updateImageLink("", { question: i, option: null })}
Then CloseIcon does not render and the state does not get updated as well.
The state of class is as follows:
this.state = {
questions: [
{
questionText: "Question 1",
questionImage:null,
options: [
{ optionText: "Option 1",
optionImage: null },
{ optionText: "Option 2",
optionImage: null },
{ optionText: "Option 3",
optionImage: null },
{ optionText: "Option 4",
optionImage: null }
],
correctAnswer: ""
}
],
openUploadImagePop: false,
imagePositionData: {
question: null,
option: null
}
}
So, how to render the CloseIcon only when the image is inserted?
I solved this question by updating the state as follows:
this.state = {
questions: [
{
questionText: "Question 1",
options: [
{ optionText: "Option 1" },
{ optionText: "Option 2" },
{ optionText: "Option 3" },
{ optionText: "Option 4" }
],
correctAnswer: ""
}
],
openUploadImagePop: false,
imagePositionData: {
question: null,
option: null
}
};
}
Here as there's no questionImage or optionImage field the unnecessary CloseIcon rendering problem is solved. Whenever, image is uploaded questionImage or optionImage gets added in the state through updateImageLink function.

How to pass a sectionlist sectionHeader's index to the reducer?

Looking to map items with index using SectionList, I was successfully able to map the index of the sections and pass the state to the reducer, however, the section header has a different index and would like to do the same with it. Help me up with some examples if possible. This is something that I am developing for a food tech app which and I want to implement the Cart Functionality in the App.
SectionList:
<SectionList
sections={this.props.user.dailyMenuData.item.map(
({category, data}, index2) => ({category, data, index2}),
)}
keyExtractor={this.keyExtractor}
renderItem={this.renderMenu}
renderSectionHeader={({section: {category, index2}}) => (
<CText style={styles.headerStyle}>{category}</CText>
)}
/>
The above data is coming from MongoDB like below:
DATA = {
vendor_id: XXXXXX (For Mapping Vendor to the Menu)
company_id: XXXXX (For Mapping the Customer to the Menu)
item: [
{
category: 'A La Carte',
data: [
{
src:
'https://cdn.pixabay.com/photo/2017/08/01/14/22/fruits-2565817_960_720.jpg',
name: 'Coffee with Pancakes',
price: '160',
rating: 3.8,
calorie: '130',
},
}],
},
The AddtoCart Reducer is dynamically getting the value of the index of data[] however it is not able to get the index of item[] from the API called. The reducer code is given below:
case ADDTOCART:
return update(state, {
dailyMenuData: {
item: {
1: {
data: {
[payload.index]: {
quantity: {
$set:
state.dailyMenuData.item[1].data[payload.index].quantity +
1,
},
},
},
},
},
},
})

Make a Tree view from JSON data using React JS

First of all i am very new to React JS. So that i am writing this question. I am trying this for three days.
What I have to do, make a list of category, like-
Category1
->Sub-Category1
->Sub-Category2
Categroy2
Category3
.
.
.
CategoryN
And I have this json data to make the listing
[
{
Id: 1,
Name: "Category1",
ParentId: 0,
},
{
Id: 5,
Name: "Sub-Category1",
ParentId: 1,
},
{
Id: 23,
Name: "Sub-Category2",
ParentId: 1,
},
{
Id: 50,
Name: "Category2",
ParentId: 0,
},
{
Id: 54,
Name: "Category3",
ParentId: 0,
},
];
I have tried many open source examples, but their json data format is not like mine. so that that are not useful for me. I have build something but that is not like my expected result. Here is my jsfiddle link what i have done.
https://jsfiddle.net/mrahman_cse/6wwan1fn/
Note: Every subcategory will goes under a category depend on "ParentId",If any one have "ParentId":0 then, it is actually a category, not subcategory. please see the JSON
Thanks in advance.
You can use this code jsfiddle
This example allows to add new nested categories, and do nested searching.
code with comments:
var SearchExample = React.createClass({
getInitialState: function() {
return {
searchString: ''
};
},
handleChange: function(e) {
this.setState({
searchString: e.target.value.trim().toLowerCase()
});
},
isMatch(e,searchString){
return e.Name.toLowerCase().match(searchString)
},
nestingSerch(e,searchString){
//recursive searching nesting
return this.isMatch(e,searchString) || (e.subcats.length && e.subcats.some(e=>this.nestingSerch(e,searchString)));
},
renderCat(cat){
//recursive rendering
return (
<li key={cat.Id}> {cat.Name}
{(cat.subcats && cat.subcats.length) ? <ul>{cat.subcats.map(this.renderCat)}</ul>:""}
</li>);
},
render() {
let {items} = this.props;
let {searchString} = this.state;
//filtering cattegories
if (searchString.length) {
items = items.filter(e=>this.nestingSerch(e,searchString))
console.log(items);
};
//nesting, adding to cattegories their subcatigories
items.forEach(e=>e.subcats=items.filter(el=>el.ParentId==e.Id));
//filter root categories
items=items.filter(e=>e.ParentId==0);
//filter root categories
return (
<div>
<input onChange={this.handleChange} placeholder="Type here" type="text" value={this.state.searchString}/>
<ul>{items.map(this.renderCat)}</ul>
</div>
);
}
});

Categories