Reputation: 49
I'm new to react and programming in general, I have searched and only found solutions for js not react specific.
Having trouble displaying next or previous item in an array passed via props. When Next button is clicked I only see the same item in the array being returned not the next item, I understand previous will return null as displaying first item on load.
import React, { Component } from 'react'
import VideoPlayer from './Video'
import axios from 'axios'
export default class App extends Component {
constructor(props) {
super(props);
this._TogglePrev = this._TogglePrev.bind(this);
this._ToggleNext = this._ToggleNext.bind(this);
// app state
this.state = {
videos: [],
selectedVideo: null
}
}
componentDidMount() {
axios.get('http://localhost:5000/v1/video?id=287948764917205')
.then((result)=> {
var videos = result.data.payload
this.setState({
videos: videos,
selectedVideo: videos[0]
});
})
}
componentWillUnmount() {
this.serverRequest.abort()
}
// State transitions
_ToggleNext() {
console.log("something worked");
// take a copy of our state
const selectedVideo = this.state.selectedVideo;
// next video
var i = 0,
max = selectedVideo.length;
for (i; i < max; i += 1) {
if (selectedVideo[i]) {
return selectedVideo[i + 1];
}
}
//set our state
this.setState( selectedVideo );
console.log(selectedVideo)
}
_TogglePrev() {
console.log("something worked");
var current = this.state.selectedVideo;
var prev = current - 1;
if (prev < 0) {
prev = this.state.videos.length - 1;
}
// update our state
this.setState({ prev });
}
render() {
return (
<div className="App" style={{width: '100%', height: '100%'}}>
<div className="controls">
<button className="toggle toggle--prev" onClick={this._TogglePrev}>Prev</button>
<button className="toggle toggle--next" onClick={this._ToggleNext}>Next</button>
</div>
<VideoPlayer video={this.state.selectedVideo} />
</div>
)
}
}
The returned data
[
{ eventId: "287948764917205"
userName: "Jon Doe"
videoLink: "https://"https:s3.amazonaws.com/...""
userPhotoLink: "https://"https:s3.amazonaws.com/...""
},
{ eventId: "287948764917205"
userName: "Jane Thompson"
videoLink: "https://"https:s3.amazonaws.com/...""
userPhotoLink: "https://"https:s3.amazonaws.com/...""
}
]
Upvotes: 0
Views: 12403
Reputation: 936
Use document.activeElement
in order to get the currently focused element. Then, use nextElementSibling
on order to get the next element then focus()
just like thisdocument.activeElement.nextElementSibling.focus()
export default function TextField() {
return (
<div
onKeyDown={(e:any)=>{
if (e.keyCode==13){
const active:any = document.activeElement
active.nextElementSibling.focus()
}
}}
>
<input/>
<input/>
<input/>
</div>
);
};
Upvotes: 1
Reputation: 104529
Mistakes:
1. If you use return
keyword inside for
loop it will not only break the loop
, it will return from that function also, so in these lines:
for (i; i < max; i += 1) {
if (selectedVideo[i]) {
return selectedVideo[i + 1];
}
}
this.setState( selectedVideo );
....
If if(selectedVideo[i])
will return true then it will break the loop and return from the function, so the lines after this for
loop will never executes because of that return statement.
2. setState
is a function and we need to pass an object
(key-value pair, key will be the state variable names) in this, so you need to write it like this:
this.setState({ selectedVideo }); or this.setState({ selectedVideo: selectedVideo }); //both are same
Another way of writing the code by maintaining index:
1. Instead of maintaining selectedVideo
in state variable maintain the index only, index of item of the array.
2. On click of next and prev button, increase or decrease the value of index and use that index to pass specific object of the state videos array to child component.
Like this:
import React, { Component } from 'react'
import VideoPlayer from './Video'
import axios from 'axios'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
videos: [],
selectedIndex: 0
}
this._TogglePrev = this._TogglePrev.bind(this);
this._ToggleNext = this._ToggleNext.bind(this);
}
componentDidMount() {
axios.get('http://localhost:5000/v1/video?id=287948764917205')
.then((result)=> {
var videos = result.data.payload
this.setState({
videos: videos,
selectedIndex: 0
});
})
}
componentWillUnmount() {
this.serverRequest.abort()
}
_ToggleNext() {
if(this.state.selectedIndex == this.state.videos.length - 1)
return;
this.setState(prevState => ({
selectedIndex: prevState.selectedIndex + 1
}))
}
_TogglePrev() {
if(this.state.selectedIndex == 0)
return;
this.setState(prevState => ({
selectedIndex: prevState.selectedIndex - 1
}))
}
render() {
let {selectedIndex, videos} = this.state;
return (
<div className="App" style={{width: '100%', height: '100%'}}>
<div className="controls">
<button className="toggle toggle--prev" onClick={this._TogglePrev}>Prev</button>
<button className="toggle toggle--next" onClick={this._ToggleNext}>Next</button>
</div>
<VideoPlayer video={videos[selectedIndex]} />
</div>
)
}
}
Upvotes: 3
Reputation: 10324
It's better to write in the constructor:
constructor(props) {
super(props);
this._TogglePrev.bind(this);
this._ToggleNext.bind(this);
// app state
this.state = {
videos: [],
selectedVideo: null,
selectedVideoIndex:0
}
}
and also change
_ToggleNext() {
console.log("something worked");
// take a copy of our state
const selectedVideo = this.state.selectedVideo;
// next video
var selectedVideoIndex = this.state.selectedVideoIndex; //i always starts with zero ????? you need also to save the index
max = selectedVideo.length;
for (selectedVideoIndex; selectedVideoIndex < max; selectedVideoIndex++) {
if (selectedVideo[selectedVideoIndex]) {
const retval = selectedVideo[selectedVideoIndex + 1];
this.setState( selectedVideoIndex+1 );
this.setState(retval );
return retval;
}
}
console.log(selectedVideo)
}
Upvotes: 0