Reputation: 1049
I am trying to loop through certain elements in React as i need to render part of an array per each view.
Array rendering has to start from ArrayIndexStart and end at ArrayIndexEnd.
Here is what i got:
var ObjectArray =[{"letter":"a"},{"letter":"b"},{"letter":"c"},{"letter":"d"},{"letter":"e"},{"letter":"f"},{"letter":"g"},{"letter":"h"},{"letter":"i"},{"letter":"j"},{"letter":"k"},{"letter":"l"},{"letter":"ł"},{"letter":"m"},{"letter":"n"},{"letter":"ń"},{"letter":"o"},{"letter":"ó"},{"letter":"p"},{"letter":"q"},{"letter":"r"},{"letter":"s"},{"letter":"ś"},{"letter":"t"},{"letter":"u"},{"letter":"v"},{"letter":"w"},{"letter":"x"},{"letter":"y"},{"letter":"z"},{"letter":"ź"},{"letter":"ż"}];
class ImageViewer extends React.Component {
constructor() {
super();
this.state = {
ArrayIndexStart: 0,
ArrayIndexEnd: 8,
}
this.handleButtonLeft = this.handleButtonLeft.bind(this);
this.handleButtonRight = this.handleButtonRight.bind(this);
}
handleButtonLeft(ArrayIndexStart, ArrayIndexEnd, event) {
if (ArrayIndexStart >= 8) {
this.setState({ ArrayIndexEnd: ArrayIndexEnd,ArrayIndexStart: ArrayIndexStart})
}
else {
this.setState({ ArrayIndexEnd: 8,ArrayIndexStart: 0 })
}
}
handleButtonRight(ArrayIndexStart, ArrayIndexEnd, event) {
if (ArrayIndexEnd <= ObjectArray.length) {
this.setState({ ArrayIndexStart: ArrayIndexStart,ArrayIndexEnd: ArrayIndexEnd })
}
else {
this.setState({ ArrayIndexStart: 24,ArrayIndexEnd: ObjectArray.length })
}
}
render() {
return(
<div>
<button onClick={() => this.handleButtonLeft(this.state.ArrayIndexStart - 8, this.state.ArrayIndexEnd - 8)}>left</button>
<button onClick={() => this.handleButtonRight(this.state.ArrayIndexStart + 8, this.state.ArrayIndexEnd + 8)}>right</button>
<div>
<p>{this.state.ArrayIndexStart}</p>
<p>{this.state.ArrayIndexEnd}</p>
</div>
</div>
)
for(var i = this.state.ArrayIndexStart;i<this.state.ArrayIndexEnd;i++)
{
return(
<div>
<p>{ObjectArray[i].letter}</p>
</div>
)
}
}}
ReactDOM.render(
<ImageViewer />,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Upvotes: 1
Views: 512
Reputation: 4039
All the code after your first return statement from render()
is ignored - once the function had returned then its execution stops. It is often useful to use a tool like ESLint which can tell you when this is the case and guide you to writing better code.
In your case then you could loop over the ObjectArray with a for
loop to create the elements you need, but it is much easier to use some functional programming techniques to do this within your JSX.
I have updated your snippet to show one way of doing this. It uses the slice function first:
ObjectArray.slice(startIndex, endIndex)
which returns a new array containing only the elements between start and end index. For example,
[1,2,3,4,5,6].slice(1, 3); // returns [2,3,4]
Once we have sliced the part of the array that we need, we can then use the map
function to transform each element of the array into the form that we need.
ObjectArray.map(obj => obj.letter);
The map function takes a single argument (the lambda function obj => obj.letter
) which will be applied in turn to each member of the array.
A simpler example might be doubling each number in an array:
[1,2,3,4].map(x => x * 2); // returns [2,4,6,8];
I have also made some changes to simplify your click handler functions. It uses the functional setState argument, i.e.
this.setState(previousState => {
return {
// state update object
}
});
This is the correct approach to use when your next state depends on the value of your previous state - in your code the next index depends on the value of the previous index. It also greatly simplifies the JSX by allowing you to do:
onClick={this.handleButtonClick(increment)}
For both buttons, passing a negative increment to go "left" and a positive increment to go "right".
var ObjectArray =[{"letter":"a"},{"letter":"b"},{"letter":"c"},{"letter":"d"},{"letter":"e"},{"letter":"f"},{"letter":"g"},{"letter":"h"},{"letter":"i"},{"letter":"j"},{"letter":"k"},{"letter":"l"},{"letter":"ł"},{"letter":"m"},{"letter":"n"},{"letter":"ń"},{"letter":"o"},{"letter":"ó"},{"letter":"p"},{"letter":"q"},{"letter":"r"},{"letter":"s"},{"letter":"ś"},{"letter":"t"},{"letter":"u"},{"letter":"v"},{"letter":"w"},{"letter":"x"},{"letter":"y"},{"letter":"z"},{"letter":"ź"},{"letter":"ż"}];
class ImageViewer extends React.Component {
constructor() {
super();
this.state = {
ArrayIndexStart: 0,
ArrayIndexEnd: 8
};
this.handleButtonClick = this.handleButtonClick.bind(this);
}
handleButtonClick(increment) {
this.setState(prevState => {
if (prevState.ArrayIndexStart + increment >= 8 &&
prevState.ArrayIndexEnd + increment <=
ObjectArray.length) {
return {
ArrayIndexEnd: prevState.ArrayIndexEnd + increment,
ArrayIndexStart: prevState.ArrayIndexStart + increment
};
} else if (increment < 0) {
return {
ArrayIndexEnd: 8,
ArrayIndexStart: 0
};
} else {
return {
ArrayIndexEnd: ObjectArray.length,
ArrayIndexStart: ObjectArray.length - increment
}
}
});
}
render() {
return(
<div>
<button onClick={() => this.handleButtonClick(-8)}>left</button>
<button onClick={() => this.handleButtonClick(8)}>right</button>
<div>
<p>{this.state.ArrayIndexStart}</p>
<p>{this.state.ArrayIndexEnd}</p>
</div>
{ObjectArray.slice(this.state.ArrayIndexStart, this.state.ArrayIndexEnd
).map(obj => obj.letter)
}
</div>
)
}}
ReactDOM.render(
<ImageViewer />,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Upvotes: 2
Reputation: 938
No a return statement ends where the return is made, so you can't return twice and hope to see both, the render function will stop after the first return.
An easy .map()
function to iterate and return each object to your render function, this will be your golden key here. consider this code:
render() {
return <div>
<button onClick={() => this.handleButtonLeft(this.state.ArrayIndexStart - 8, this.state.ArrayIndexEnd - 8)}>left</button>
<button onClick={() => this.handleButtonRight(this.state.ArrayIndexStart + 8, this.state.ArrayIndexEnd + 8)}>right</button>
<div>
<p>{this.state.ArrayIndexStart}</p>
<p>{this.state.ArrayIndexEnd}</p>
</div>
<div>
{ObjectArray.slice(this.state.ArrayIndexStart, this.state.ArrayIndexEnd).map(item => {
return <p>{item.letter}</p>
})}
</div>
</div>
}
Upvotes: 1