How to run map inside map function in Reactjs - reactjs

I want my axios part should run first inside useEffect so that my state can be update first and then further I can use that.
Here is error:
TypeError: Cannot read property map of undefined
When I console it shows states is not updated it holds SwitchCOM empty array
That means it directly goes for the return statement without running useEffect axios part.
This is what my SwitchCom state look like:
SwitchCOM: {
0: {id: "36", name: "XYZ", progress: "", details: [{id: "36", name: "XYZ", progress: ""}]},
1: {id: "83", name: "ABC", progress: "", details: [{id: "36", name: "XYZ", progress: ""}]},
2: {id: "77", name: "EFG", progress: "", details: [{id: "36", name: "XYZ", progress: "" }]}
}
const initialState = {
SwitchCOM: [],
isFetching: false,
hasError: false
}
{states.SwitchCOM.map(topis => (
<div className="item" key={topis.id}>
<p>{topis.name}</p>
<p>
<progress id="file" value="32" max="100">
{topis.progress}
</progress>
</p>
{topis.activities.map(activity => (
<table key={activity.id}>
<tbody>
<tr>
<td>Name</td>
<td>Progress</td>
<td>Status</td>
</tr>
<tr >
<td>{activity.name}</td>
<td>{activity.prog}</td>
</tr>
</tbody>
</table>
))}
</div>
))}

You are trying to map through an object which won't work. Instead you need to use Object.keys(...) to accomplish what you want here.
You should do something like this:
{Object.keys(states.SwitchCOM).map(key => (
<div className="item" key={states.SwitchCOM[key].id}>
<p>{states.SwitchCOM[key].name}</p>
<p>
<progress id="file" value="32" max="100">
{states.SwitchCOM[key].progress}
</progress>
</p>
{states.SwitchCOM[key].details.map(detail => (
<table key={detail.id}>
<tbody>
<tr>
<td>Name</td>
<td>Progress</td>
</tr>
<tr>
<td>{detail.name}</td>
<td>{detail.progress}</td>
</tr>
</tbody>
</table>
))}
</div>
))}

Related

How to call nested object list on table list

Hi im newbie on react js,
how to call nested object(array/list) on main object, i mean object in object
<tbody>
{
vehicles.map((v, index) =>(
<tr key={v.id}>
<td>{index +1}</td>
<td>{v.type}</td>
<td>{v.plateNumber}</td>
{v.employee.map(item => {
return (
<td>
<ul>{item.name}</ul>
</td>
);
})}
<td>
<Link className="btn btn-info" to={`/vehicles/edit/${v.id}`}>Update</Link>
<button className="btn btn-danger ml-2" onClick={() => {deleteSweetAlert(v.id)}}>Delete</button>
</td>
</tr>
))
}
</tbody>
This one my JSON example
[
{
"id": 1,
"type": "MasterCard",
"plateNumber": "3747948",
"status": "1",
"employee": {
"id": 1,
"name": "Joanne Hagenes Sr.",
"location": "60794 Rippin Cove Suite 080\nTroyberg, ND 95778",
"department": "Wuckert-Luettgen",
"status": "1"
}
}
]
I always get this error message at the console
react-dom.development.js:26874 Uncaught TypeError: v.employee.map is not a function
map() function can only applied with an array, so in your case employee should be an array instead an object:
{
"id": 1,
"type": "MasterCard",
"plateNumber": "3747948",
"status": "1",
"employee": [{
"id": 1,
"name": "Joanne Hagenes Sr.",
"location": "60794 Rippin Cove Suite 080\nTroyberg, ND 95778",
"department": "Wuckert-Luettgen",
"status": "1"
}]
}
Another way to fix this, since each of your vehicle contains only 1 employee (based on how u named it). So i suppose you dont need to use map() function in this case:
<tbody>
{
vehicles.map((v, index) =>(
<tr key={v.id}>
<td>{index +1}</td>
<td>{v.type}</td>
<td>{v.plateNumber}</td>
<td>
<ul>{item.name}</ul>
</td>
<td>
<Link className="btn btn-info" to={`/vehicles/edit/${v.id}`}>Update</Link>
<button className="btn btn-danger ml-2" onClick={() => {deleteSweetAlert(v.id)}}>Delete</button>
</td>
</tr>
))
}
</tbody>
You can use interface to define.
interface IFoo {
foo: string;
}
interface IBaz {
baz: string;
foo: IFoo;
}
const obj: IBaz = {
baz: 'bar',
foo: {
foo: 'foo',
},
};
console.log(obj.baz); // -> baz
console.log(obj.foo.foo); // -> foo

VueJS - how build dynamic values, using the mustaches?

In data, I have 2 arrays.
In the template, I want to use value of a special key of an array, to target the second array.
<template>
<table>
<tr v-for="sa in mySecondArray">
<td v-for="fa in myFirstArray">
{{ ??? }}
</td>
</tr>
</table>
</template>
// ...
data() {
myFirstArray: [
{
a: "KeyOne",
b: "we don't care",
c: "we don't care",
},
{
a: "KeyTwo",
b: "we don't care",
c: "we don't care",
},
],
mySecondArray: [
{
KeyOne: "foo",
KeyTwo: "bar"
},
{
KeyOne: "hello",
KeyTwo: "world"
},
],
In this exemple, I want to display
<table>
<tr>
<td>foo</td>
<td>hello</td>
</tr>
<tr>
<td>bar</td>
<td>world</td>
</tr>
</table>
I tried :
<tr v-for="sa in mySecondArray">
<td v-for="fa in myFirstArray">
{{ sa + fa.a }}
</td>
</tr>
in this case it displays [object Object].
I tried :
<tr v-for="sa in mySecondArray">
<td v-for="fa in myFirstArray">
{{ sa.concat('.',fa.a) }}
</td>
</tr>
in this case console says: "sa.concat is not a function".
I also tried with quotes, but it just concats the strings: "sa.KeyOne".
How to make this final string used as a target and not just a string ?
You can do something like this to get your result,
new Vue({
el: '#app',
data: {
firstArray: [{
a: "KeyOne",
b: "we don't care",
c: "we don't care",
},
{
a: "KeyTwo",
b: "we don't care",
c: "we don't care",
}],
secondArray: [
{
KeyOne: "foo",
KeyTwo: "bar"
},
{
KeyOne: "hello",
KeyTwo: "world"
},
]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/css/bootstrap.min.css" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<div id="app">
<table class="table">
<tr>
<th>head1</th>
<th>head2</th>
</tr>
<tr v-for="(sa1, index1) in secondArray" >
<td v-for="(sa2, index2) in secondArray">
{{secondArray[index2][firstArray[index1].a]}}
</td>
</tr>
</table>
</div>
Hope this solves your problem!

Unable to update react state from user input data

import React, { Component, Fragment } from "react";
import "./App.css";
export default class App extends Component {
constructor(props){
super(props)
this.state = {
data: [
{
id: 1,
Firstname: "Jill",
Lastname: ["john", "hobss", "smith"],
Age: [1, 2, 3],
company: ["facebook", "google", "netflix"],
skills: ["python", "java", "scala"]
},
{
id: 2,
Firstname: "Jill",
Lastname: ["john", "hobss", "smith"],
Age: [1, 2, 3],
company: ["facebook", "google", "netflix"],
skills: ["python", "java", "scala"]
},
{
id: 3,
Firstname: "Jill",
Lastname: ["john", "hobss", "smith"],
Age: [1, 2, 3],
company: ["facebook", "google", "netflix"],
skills: ["python", "java", "scala"]
},
{
id:4,
Firstname: "Jill",
Lastname: ["john", "hobss", "smith"],
Age: [1, 2, 3],
company: ["facebook", "google", "netflix"],
skills: ["python", "java", "scala"]
}
]
}
}
handleChange = (id, company, event) => {
const data = this.state.data;
for(let d of data){
if(d.id === id){
for(let c of d.company){
if(c === company){
c = event.target.value
}
}
}
}
}
render() {
return (
<div>
<table>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
<th>company</th>
<th>skills</th>
</tr>
{
this.state.data.map(td => {
return (
<tr>
<td>{td.Firstname}</td>
<td>
<table>
<tr>
<td>{td.Lastname[0]}</td>
<td>{td.Lastname[1]}</td>
<td>{td.Lastname[2]}</td>
</tr>
</table>
</td>
<td>
<table>
<tr>
<td>{td.Age[0]}</td>
<td>{td.Age[1]}</td>
<td>{td.Age[2]}</td>
</tr>
</table>
</td>
<td>
<table>
<tr>
<td>
<input type="text" value={td.company[0]} onChange={(e) => this.handleChange(td.id, td.company[0], e)} />
</td>
<td>
<input type="text" value={td.company[1]} onChange={(e) => this.handleChange(td.id, td.company[1], e)}/>
</td>
<td>
<input type="text" value={td.company[2]} onChange={(e) => this.handleChange(td.id, td.company[2], e)}/>
</td>
</tr>
</table>
</td>
<td>
<table>
<tr>
<td>{td.skills[0]}</td>
<td>{td.skills[0]}</td>
<td>{td.skills[0]}</td>
</tr>
</table>
</td>
</tr>
)
})
}
</table>
</div>
)
}
}
Here i am trying to update my table using input data .
I am sending data using event to handleChange() function and changing data of state.
But It is not working please have a look.
I am not able to change input value also.
Please have a look
if any way to solve this issue.
Thanks
I am sending data using event to handleChange() function and changing data of state.
But It is not working please have a look.
I am not able to change input value also.
Please have a look
if any way to solve this issue.
Thanks
You are currently mutating state which is an anit-pattern in react. In order to update state you need to call this.setState(newState) which will then trigger your component to rerender with the new state values;
You should replace the value attribute of the input with defaultValue so it can be changed in the first place, then use setState in your handleChange method to update the data.

react table row show column on button click

I have a table being built dynamically by mapping over an array. Each item in the array gets a row. One of the columns in each of these rows is a select. I only want that column's content to show when a button in the same row's next column is clicked.
My plan was to add some sort of a toggle bool property to each object in my array, but then when I try to toggle it in my button's onclick, my eslint is complaining because I'm trying to modify a property of the parameter I sent into the function called by the onclick.
What is the appropriate way to do this?
Here's the code for the table:
<table>
<tbody>
{myArray.map(row => (
<tr key={`test-${row.name}`}>
<td>
<div className="testClass">{row.id}</div>
</td>
<td>{row.name}</td>
<td>
<Select
options={this.getOptions(row.id)}
onSelect={this.onOptionSelect}
placeholder="Select something"
/>
</td>
<td><button onClick={() => { changeStuff(row); }}>{ row.myToggle ? 'Save' : 'Change something' }</button></td>
</tr>
))}
</tbody>
</table>
In click handler, you can update your array altogether to show/hide the select option.
Based on my understanding, I have tried creating below snippet. This is the way i could come up with, as per my understanding. I have maintained 'hidden' field in the array of objects. Instead of 'Select' I have used a simple button. You can change accordingly. Hope this helps.
const list = [
{
name: "Person 1",
phone: "123-4567",
id: 11,
hidden:true
},
{
name: "Person 2",
phone: "123-4567",
id: 12,
hidden:true
},
{
name: "Person 3",
phone: "123-4567",
id: 23,
hidden:true
},
{
name: "Person 4",
phone: "123-4567",
id: 34,
hidden:true
},
{
name: "Person 5",
phone: "123-4567",
id: 45,
hidden:true
}
];
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
list: list
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(item) {
let updatedList = this.state.list.map(obj => {
if(obj.id === item.id) {
return Object.assign({}, obj, {
hidden:!item.hidden
});
}
return obj;
});
this.setState({
list : updatedList
});
}
render() {
return (
<div>
<table>
<tbody>
{this.state.list.map(item =>
<tr key={item.itemId}>
<td>
{item.name}
</td>
<td>
{item.phone}
</td>
<td >
<button hidden={item.hidden}> Action </button>
</td>
<td>
<button
className="delete"
onClick={() => this.handleClick(item)}
>
Change
</button>
</td>
</tr>
)}
</tbody>
</table>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
table td {
font-size: 14px;
font-weight: normal;
padding: 10px;
border: 1px solid #eee;
}
<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="app"></div>

How to use an array on ng-model

This is my code http://plnkr.co/edit/oxtojjEPwkKng9iKkc14?p=preview
And I want to save object of sport and punctuation in an array, if there are one or more sports selected save it in the array like this:
likes[
{sport: 'futball', points: 1}, {sport: 'tennis', points: 1}
]
thanks!
You have to keep practicing your English a little bit more (you can ask me on the comment section in spanish if you are strugling)
I think what you are trying to do is to have a single select to be able to choose the sport and score,
Html:
<body ng-app="myapp">
<div class="main-container" ng-controller="main" ng-init="darr.dept=dept2">
<div class="client-area">
<label fo.table-container tabler="txt">Score</label>
<input type="text" id="name-txt" placeholder="Assign the score" ng-model="name">
<br />
Sport
<select ng-model="dept" ng-options="deptOpt.value as deptOpt.name for deptOpt in deptList"></select>
<br />
<button ng-click="add()">Add Item</button>
<table id="tab">
<thead>
<tr id="trow">
<th>Score</th>
<th>Sport</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="ar in arr">
<td>{{ar.name}}</td>
<td>{{ar.dept}}</td>
<td>
<button ng-click="del($index)">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
js:
var app = angular.module("myapp", []);
app.controller('main', function ($scope) {
$scope.arr = [];
$scope.deptList = [{
name: 'Football',
value: 'football'
}, {
name: 'Tennis',
value: 'Tennis'
}, {
name: 'Baseball',
value: 'baseball'
}];
$scope.dept = "football";
$scope.name = "";
$scope.add = function () {
this.arr.push({
name: this.name,
dept: this.dept
});
};
$scope.del = function (ind) {
this.arr = this.arr.splice(ind, 1);
};
$scope.editStudent = function(student) {
console.log(student);
};
});
https://jsfiddle.net/azweig/v5kbsudy/1

Resources