renderItems() {
const {items} = this.state;
const results = [];
for (let i = 0; i < items.length; i++) {
results.push(
<tr>
{
for (let j = 0; j < 8; j++) {
}
}
</tr>
)
}
}
Basically, I have an array of 32 items and would like to break it into 8 items per row (overall will be 4 rows), but the above code gives error for the inner loop inside <tr> which is correct (and im not sure how to correct it).
What would be the correct way in React to dynamically create 4 rows and put 8 tds inside each row?
You can't use a for loop directly inside the {} in JSX since it expects an expression.
You could do the for loop outside of the JSX, or chunk the items array into arrays of length 8 and map over those.
Example
renderItems() {
const items = [...this.state.items];
const chunks = [];
while (items.length) {
chunks.push(items.splice(0, 8));
}
return chunks.map(chunk => (
<tr>{chunk.map(item => <td>{item}</td>)}</tr>
));
}
This is by no means an elegant solution, but it works:
renderItems() {
const { items } = this.state;
// first, create all the <td> elements and store them in a list
let allTDs = []
for (let i = 0; i < items.length; i++) {
allTDs.push(<td key={ items[i] }> { items[i] } </td>)
}
//then break the list into four rows and keep them in separate lists
let tr1 = [];
let tr2 = [];
let tr3 = [];
let tr4 = [];
// keep count for each row
let count = 0
for (let td of allTDs) {
//first eight goes to the first row, second eight to the second etc.
if(count < 8) {
tr1.push(td)
} else if (count < 16) {
tr2.push(td)
} else if (count < 24) {
tr3.push(td)
} else if (count < 32) {
tr4.push(td)
}
count += 1;
}
// bring all four rows together in a list so that you can return that list
let allTRs = [];
allTRs.push(tr1, tr2, tr3, tr4)
return allTRs
}
render() {
return (
<div>
<table>
<tbody>
// serve each row by calling the renderItems() method and indexing
// the relevant row
<tr>{ this.renderItems()[0] }</tr>
<tr>{ this.renderItems()[1] }</tr>
<tr>{ this.renderItems()[2] }</tr>
<tr>{ this.renderItems()[3] }</tr>
</tbody>
</table>
</div>
)
}
Related
I'm currently encountering a problem when i'm calling a for loop in a functional/class component in React. For exemple if I want to create a simple function to render multiple td tr in a table React is going to infinite call the function.
class ReserveView extends Component {
createTable() {
const table = []
for (let i = 0; i < 3; i + 1) {
const children = []
for (let j = 0; j < 5; j + 1) {
children.push(<td>{`Column ${j + 1}`}</td>)
}
table.push(<tr>{children}</tr>)
}
return table
}
render() {
return (
<div>
<table>
{this.createTable()}
</table>
</div>
)
}
If i console.log(j) the console will output
this
I'm using React for a year now and it's the first time I'm having this issue. Thanks a lot for your help
Oh yeah, your problem lies in the fact that you never increase the i and j loop variant.
you need to do i++ and j++ instead of j + 1 :)
Change your +1s to ++
for (let i = 0; i < 3; i++) {
const children = []
for (let j = 0; j < 5; j++) {
children.push(<td>{`Column ${j + 1}`}</td>)
}
table.push(<tr>{children}</tr>)
}
return table
The correct answer has been posted above. Just a note that you may try ES6 map() function. It would be very useful when you are coding with React.
createTable2() {
const rows = Array(3).fill(null);
const columns = Array(5).fill(null);
return rows.map((item, ridx) => (
<tr>
{columns.map((item, cidx) => (
<td>{`Row ${ridx + 1} - Column ${cidx + 1}`}</td>
))}
</tr>
));
}
Check out the demo here: https://codesandbox.io/s/table-demo-fgd9i
I am trying to achieve a method in which the array steps got filled with new data every time I click on the button of Create New array, but instead of that, the data is getting appended instead of updating.
here are my states :
const [arr , setArray] = useState(createArray())
const [steps , setSteps] = useState([]);
const [selectedAlgorithm , setSelectedAlgorithm] = useState ();
here is my create new Array function :
const handleCreateNewData = ()=>{
let newarr = createArray();
setArray ([]);
setArray([...newarr]);
setSteps ([]);
setTimeout(()=>{
if ( algorithms[selectedAlgorithm] !== undefined){
algorithms[selectedAlgorithm](arr, steps , setSteps);
console.log('running')
}
},2000)
}
here is my bubble sort algorithm :
export const BubbleSort = (array , steps ,setSteps) =>{
let funarray = new Array();
funarray = [...array] ;
for (let i = 0 ; i < funarray.length-1 ; i++){
for(let j = 0 ; j < funarray.length-1 ; j++){
if(funarray[j]>funarray[j+1]){
[funarray[j],funarray[j+1]] = [funarray[j+1],funarray[j]]
setSteps([...steps, funarray])
steps.push(funarray.slice());
console.log('Working')
}
}
}
return funarray;
}
What is supposed to do is every time I click on create new array it should generate a new set of arrays but instead of creating new arrays it just appending the new arrays in the old steps.
You can create a temp array to hold the steps, then when the loops are done, call setSteps:
const BubbleSort = (array, steps, setSteps) => {
let funarray = [];
funarray = [...array];
let temp = [];
for (let i = 0; i < funarray.length - 1; i++) {
for (let j = 0; j < funarray.length - 1; j++) {
if (funarray[j] > funarray[j + 1]) {
[funarray[j], funarray[j + 1]] = [funarray[j + 1], funarray[j]];
temp.push(funarray)
}
}
}
setSteps(temp);
return funarray;
};
Sample: https://codesandbox.io/s/cool-wind-ijj7z?file=/src/App.js
I have an object within an object and i would like to convert the inner one to a string separated comma but it generates an infinite loop
After an observable http request am getting the data this way
this._categoryService.getChecklistCategories()
.subscribe(
res => {
this.categories = res;
let newitem:string[];
for(var i=0; i<res.length; i++){
this.categories.map((category, i) => category.no = i+1);
var obj = res[i].assigned; //an obect.
console.log(obj[0]); //get the first index
}
})
The above console.log(obj[0]) generates
I would like to create a string of truck_subtype and append it to this.categories
I have tried the following
res => {
this.categories = res;
let newitem:string[];
for(var i=0; i<res.length; i++){
this.categories.map((category, i) => category.no = i+1);//this adds no i,2,3...
var obj = res[i].assigned; //array item
let stringArray: Array<any> = [];
for(var i=0; i<obj.length; i++){
stringArray.push(obj[i].truck_subtype);
}
this.categories.map((category, i) => category.assigned= stringArray)
}
}
The above generates an infinite loop and fails to add the string of array to this.categories
Where am i wrong
May be the i variable that are declared four times (in for's and in map's), I think your index never gets to the res.length because when you use map you are resigning it.
Try to change the i's inside map to another name like i2..., and test it to see if the loops goes away.
res => {
this.categories = res;
let newitem:string[];
for(var i=0; i<res.length; i++){
this.categories.map((category, i2) => category.no = i+1);//this adds no i,2,3...
var obj = res[i].assigned; //array item
let stringArray: Array<any> = [];
for(var i3 =0; i<obj.length; i++){
stringArray.push(obj[i3].truck_subtype);
}
this.categories.map((category, i4) => category.assigned= stringArray)
}
}
Am retrieving data from database and i would like to add a number column to the data
users:any[];
onGetUsers() {
this._userService.getUsers()
.subscribe(
res => {
this.users = res
for(var i=0; i<res.length; i++) {
//append the value of i to each row of the users
}
this.initialloading = false;
}
);
}
I would like to append the value of i to each row of the users array.
So the final data can be
currently when i console.log(users) am getting
users:
firstname:name1, second:name2 ....
firstname: john, second:king ...
Now i would like to add another column called no to the returned users array in the for loop so that i have
users:
no:0, firstname:name1, second:name2 ....
no:1, firstname: john, second:king ...
How do i go about this
Use map:
this.users = res
this.users.map((user, i) => user.no = i);
Its simple because you use any[].
for(var i = 0; i < res.length; i++){
res[i].no = i;
}
But you do not iterate through res, you iterate through users
for(var i = 0; i < this.users.length; i++){
users[i].no = i;
}
...or with forEach!
this.users.forEach((user,index) -> {
user.no = index;
});
Is there any built-in feature on AngularJS to avoid ng-repeater to receive duplicated entries?
Right now I'm using the following code to prevent it:
$scope.tags = ['black','white','red','yellow','blue'];
$scope.selectedTags = [];
// textarea value
var words = $scope.message.split(' ');
for(var j = 0; j < words.length; j++) {
for (var k = 0; k < $scope.selectedTags.length; k++) {
if ($scope.selectedTags[k].Name == words[j]) {
contains = true;
}
}
if (!contains)
{
$scope.selectedTags.push($scope.tags[i]);
contains = false;
}
}
Angular UI has a unique filter:
Filters out all duplicate items from an array by checking the specified key
Alternatively, if it's just a string array you can filter your array like:
arr.filter(function (e, i, arr) {
return arr.lastIndexOf(e) === i;
});