Javascript destructuring data in react - javascript

I am using react-native and I am trying to pass data to child component, and after that I want to use map method for displaying user data with key value.
So i get this data after making array from object, how should i destruct it to get username etc..
PARENT COMPONENT:
render() {
let userMap = Object.entries(this.state.users).map(key => key);
return (
<ViewPager
users={userMap}
usersRetrieved={this.state.usersRetrieved}
addNewMatch={this.addNewMatch}
navigation={this.props.navigation}
/>
);
CHILD COMPONENT:
<Text>{JSON.stringify(props.users)}</Text>
How should i get username or profile_picture data?
I tried to do props.users[0].username but no luck
DATA EXAMPLE WITH 3 USERS:
{
"lwcIQTcpAae4e38hrD2K5Ar76W93": {
"email": "emilissssss#temp.lt",
"fbid": "3008*******71455",
"gender": "male",
"profile_picture": "...",
"username": "Emilis"
},
"tempuser": {
"email": "temp#temp.lt",
"fbid": 315151515,
"gender": "female",
"matches": {
"lwcIQTcpAae4e38hrD2K5Ar76W93": [Object]
},
"profile_picture": "...",
"username": "Egle"
},
"thirdUserID":{
"email": "temp#temp.lt"
"username": "thirdUserUsername"
...
}
}

Have you tried doing props.users[0][1].username instead? Since it seems to be the second value of an array inside an array

You can update userMap variable in parent component like
let userMap = Object.entries(this.state.users).map(([key, value]) => value);
This returns an array of user objects like:
[{
"email": "emilissssss#temp.lt",
"fbid": "3008*******71455",
"gender": "male",
"profile_picture": "...",
"username": "Emilis"
},
{
"email": "temp#temp.lt",
"fbid": 315151515,
"gender": "female",
"matches": {
"lwcIQTcpAae4e38hrD2K5Ar76W93": [Object]
},
"profile_picture": "...",
"username": "Egle"
},
{
"email": "temp#temp.lt"
"username": "thirdUserUsername"
...
}
]
Then in child component you can simply .map() over all users like:
{props.users.map(user => (
<Text>{user.username}</Text>
))}
Edit:
As, you need the userid also, then update userMap variable in parent component like:
let userMap = Object.entries(this.state.users);
Then in the child component, update map like:
{props.users.map(([key, user]) => (
<Text>{key}</Text>
<Text>{user.username}</Text>
))}
Or,
{props.users.map(([key, user]) => (
<Text>{key + ', ' + user.username}</Text>
))}

You can do the following thing:
{props.users.map(user => (
<Text>{user[0].username}</Text>
))}

What are you trying to do with Object.entries(this.state.users).map(key => key); ? Object.entries already returns an array so there's no need to map it afterwards like that I reckon.
Anyway, to destructure an object in js:
const obj = {
a: "value",
b: "other value",
}
const {a,b} = obj
// a "value", b "other value"
Note that the variable and the key should be named the same.
And now you have a and b as constants available in your code.
In your child component you could have smth like this:
render() {
let users = props.users
return users.map(user => {
const {username, email} = user; // destructure whatever you want
return <Text>{email} {username}</Text> // display it the wy you want
});
}

Array appears to be tied up several times.
The value you want is in the second index of the second array.
{props.users.map(user => (
<Text>{user[1].username}</Text>
))}

Related

Filter object by name with JavaScript

I made a request to an endpoint and I get this object, I'm filtering the name like this:
fetch('http://endpoint', requestOptions)
.then((response) => response.json())
.then((result) => {
const onlineUsers = result.resource.items[1].onlineUsers >= 1;
console.log(onlineUsers);
})
.catch((error) => console.log('error', error));
This workers, but I just need the result of what is in the key named Forms, but there is a possibility that it will change its position, so the items[1] it may not work anymore
This is an example of the object I receive:
{
"type": "application/vn+json",
"resource": {
"total": 4,
"itemType": "application",
"items": [
{
"name": "Test",
"onlineUsers": 1
},
{
"name": "Forms",
"onlineUsers": 1
},
{
"name": "Users",
"onlineUsers": 7
},
{
"name": "OnlineUsers",
"onlineUsers": 5
}
]
},
"method": "get",
"status": "success"
}
Is there any way to receive this object and filter by name? Like:
if (hasName === "Forms", get onlineUsers) {
// Do something
}
Thanks!
As suggested in your question, you can use filter on your array. Something like that:
console.log(
result.resource.items.filter((item) => item.name === "Forms")
);
This will print an array with all items having the name Forms. Using your example:
[
{
"name": "Forms",
"onlineUsers": 1
}
]
If there is only one item with the name Forms, or if you want only the first one, find may be a good alternative with a similar syntax:
console.log(
result.resource.items.find((item) => item.name === "Forms")
);
This will only print the first found object (or null if none is matching), without the array "pollution":
{
"name": "Forms",
"onlineUsers": 1
}
result.resource.items.filter((item) => item.name === "Forms")
Will filter your objects for you
Note, you will get back an array of all the filtered objects meeting the condition.
If you know there's only one object that matches that name you can use find which will return the first match so you don't necessarily need to iterate over the entire array.
Here's a little general function that might help. Pass in the data, the value of name, and the property you want the value of. If there is no match it returns 'No data'.
const data={type:"application/vn+json",resource:{total:4,itemType:"application",items:[{name:"Test",onlineUsers:1},{name:"Forms",onlineUsers:1},{name:"Users",onlineUsers:7},{name:"OnlineUsers",onlineUsers:5}]},method:"get",status:"success"};
function finder(data, name, prop) {
return data.resource.items.find(item => {
return item.name === name;
})?.[prop] || 'No data';
}
console.log(finder(data, 'Forms', 'onlineUsers'));
console.log(finder(data, 'morf', 'onlineUsers'));
console.log(finder(data, 'Users', 'onlineUsers'));
console.log(finder(data, 'Users', 'onlineUser'));

Uncaught TypeError: Cannot read properties of null - React.js

const deletePerson = (persons) => {
axios
.delete(`http://localhost:3001/persons/${persons.name}`)
.then(console.log(`done`))
.then(response => response.data)
.then(setPersons(Object.values(persons).filter(q => q.name !== false)))}
I am a newbie in React.js.
I have a problem, which I have been trying to solve for a couple of days.
I added the Button for Delete requests, and in the different ways, it returns the same type of mistake:
Uncaught TypeError: Cannot read properties of null (reading 'name').
error message
the use-case in that I am using this Button inside the resulting method, which automatically filters the list of persons:
const Filter = (props) => {return (<> {props.persons.filter(person => person.name.toLowerCase().includes(props.showFiltered.toLowerCase())).map((filteredName, id) => (
<li key={id.toString()}>
{filteredName.name} {filteredName.number} <Button text='delete' handleClick={props.deletePerson} />
</li>
))}
</>)}
Looks like you are using array values based on the entire object and not the persons value inside the object. And from the looks of it you are trying to find a name with the value false which doesn't seem to match what you have there.
Something like this is probably what you are looking for
.then(setPersons(Object.values(personsList).filter(q => q.name !== persons.name)))}
TLDR; (Updated)
const deletePerson = (persons) => {
axios
.delete(`http://localhost:3001/persons/${persons.persons.name}`)
.then(console.log(`done`))
.then((response) => response.data)
.then(() => setPersons(persons["persons"].filter((q) => q.name !== false)));
};
Explanation:
Using Object.values(persons) will return nested array which look something like this:
[
[
{ "name": "Arto Hellas", "number": "040-123456", "id": 1 },
{ "name": "Ada Lovelace", "number": "39-44-5323523", "id": 2 },
{ "name": "Dan Abramov", "number": "12-43-234345", "id": 3 },
{ "name": "Mary Poppendieck", "number": "39-23-6423122", "id": 4 }
]
]
However, you're expecting q variable to be:
[
{ "name": "Arto Hellas", "number": "040-123456", "id": 1 },
{ "name": "Ada Lovelace", "number": "39-44-5323523", "id": 2 },
{ "name": "Dan Abramov", "number": "12-43-234345", "id": 3 },
{ "name": "Mary Poppendieck", "number": "39-23-6423122", "id": 4 }
]
Therefore, there are two ways of fixing this:
Extracting the nested array
Object.values(persons) => Object.values(persons)[0]
Access the object value directly
Object.values(persons) => persons["persons"]
The error might occurred because it was a failed request since you didn't pass anything to deletePersons function.
const Filter = (props) => {
return (
<>
{props.persons
.filter((person) =>
person.name.toLowerCase().includes(props.showFiltered.toLowerCase())
)
.map((filteredName, id) => (
<li key={id.toString()}>
{filteredName.name} {filteredName.number}
<Button text="delete" handleClick={() => props.deletePerson(props.persons)} />
</li>
))}
</>
);
};

Get id in array from array object in vue js

I'm new in Vue js, and I have data in array object like below when I use vue-multiselect.
[
{
"id": 1,
"add_on_type": "Xtra",
"name": "test",
"price": 12,
"created_at": "2020-06-25 10:12:43",
"updated_at": "2020-06-25 10:12:43"
},
{
"id": 3,
"add_on_type": "Xtra",
"name": "Some x",
"price": 120,
"created_at": "2020-06-30 05:47:52",
"updated_at": "2020-06-30 05:47:52"
}
]
but in my function I need to access like key:value like below
"xtra": {
// key: value
0: 1
1: 3
}
but I get all array object instead of id only. I need to get the ID only in array, below is my code. I don't know how to get only id from array using below code.
this.$axios
.get("items/" + this.item)
.then(res => {
// below line is how I get the array object, but I need only id in array.
data.xtra = this.extra;
console.log(data);
})
.catch(err => {
throw err;
});
this maybe easy for some people, but I cannot find the way to to do. any help would be appreciated. thanks in advance
If I understood correctly your question, this.item is holding an object retrieved from the array. If is like this, it should be as easy as:
.get("items/" + this.item.id)
if you want to create new array you can do this at your return from axios
.then(res => {
let arr = res.data
this.xtra = arr.map(x =>
x.item.id)
})
First declare Items as reactive array in setup function
const tools = reactive([]);
Then in methods, retrieve
axios.get("/user-items").then(response => {
var items = [];
response.data.forEach((item, index) => {
items.push(item.id);
})
Object.assign(this.items, items);
});

How to render key value pairs from object react

This is object data that I have stored in my this.state.profile from an API request.
What I need to do know is render the values from the keys to the web broswer. I am trying with the code below which does not work. Also how do I render the objects within side this object? This is all so confusing :(
{
"localizedLastName": "King",
"lastName": {
"localized": {
"en_US": "King"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"firstName": {
"localized": {
"en_US": "Benn"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"profilePicture": {
"displayImage": "urn:li:digitalmediaAsset:C5603AQGjLGZPOyRBBA"
},
"id": "fm0B3D6y3I",
"localizedFirstName": "Benn"
}
How I am trying to render it:
const { profile } = this.state;
const profileList = Object.keys(profile).map((key,value)=>{
return (
<div>{key}{value.toString()}</div>
);
})
{ profileList }
try:
return (
{Object.entries(profile).map(([key,value]) => {
<div>{key} : {value.toString()}</div>
})}
)
the iteration needs to happen inside of the return.
You could build up your object outside your render call like below and just render it (elements).
var elements = [];
for (var prop in this.state.profile) {
elements.push(<div>{prop} : {this.state.profile[prop].toString()}</div>)
}
If it's not working my guess would be your state isn't initialised or your target js version doesn't support Object.entries
First of all, you need to deal with nested objects:
{
...
"firstName": {
"localized": {
"en_US": "Benn"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
}...
}
If you try to render the value on the key firstName, you will get a object as value, and React can't render objects as elements.
And if you call toString() on it, you will get [Object object] as value.
To solve this, you gonna need some recursion:
const objToString = obj => {
let result = [];
Object.keys(key => {
if(typeof obj[key] === 'object'){
let children = (<div>{key} : {objToString(obj[key])}</div>)
result.push(children)
} else
result.push(<div>{key} : {obj[key]}</div>)
})
}
...
const profileList = objToString(profile)
This should give you this something like:
...
<div>firstName:
<div>localized:
<div>en_US: Benn</div>
</div>
</div>
...

why this.setState going to "is not a function"?

Im trying build simple app to learn how to make api calls.
When I'm trying to setState in react with onClick function I'v created, every time I'v tried to invoke I get
not a function
I tried to bind this like this:
this.setState(() => ({
rowPos: null
}).bind(this))
but that did not worked also, I get the error:
(intermediate value).bind is not a function
there is constructor with state object:
constructor(props) {
super(props);
this.state = {
endpoint: 'https://jolapatola5.fakturownia.pl/invoices.json',
params: {
api_token: 'B5Lg3uPBCMcDNX5lsQOM/jolapatola5',
invoice: {
"kind": "vat",
"number": null,
"sell_date": "2019-07-14",
"place": 'Lublin',
"sell_date": "2019-07-14",
"issue_date": "2019-07-14",
"payment_to": "2019-07-21",
"buyer_name": "aaa",
"buyer_tax_no": "5252445767",
"buyer_street": "aaa",
"buyer_post_code": "",
"buyer_city": "",
"seller_name": 'aaa',
"seller_street": '',
"seller_post_code": '',
"seller_city": '',
"seller_bank_account": '',
"seller_tax_no": '',
positions: [{
"name": "Produkt A1",
"tax": 23,
"total_price_gross": 10.23,
"quantity": 1
},
{
"name": "Produkt A1",
"tax": 23,
"total_price_gross": 10.23,
"quantity": 1
}
]
}
}
}
this.removeProductRow = this.removeProductRow.bind(this);
}
and method I'm trying to invoke onClick:
removeProductRow(id) {
let rowPos = this.state.params.invoice.positions[id];
this.setState(() => ({
rowPos: null
}).bind(this))
console.log(rowPos)
};
id is passed when I'm mapping components
The result I'm trying to perform is set the this.state.params.invoice.position alias rowPos to null, now its an object.
Thanks for any help
EDIT: there is the way I'm mapping components:
{
this.state.params.invoice.positions.map(function(item,index){
return
<ItemRow key={index} removeProductRow={() => this.removeProductRow(index)}/>
},this)
}
setState should be binded to React.Component, when you call this.setState.bind(this) you are actually binding it to removeProductRow, just remove the .bind(this)
There are two things I would do different.
First: Fixing the remove method.
removeProductRow(index){
let positionsUpdated = this.state.params.invoice.positions.filter((_, idx) => idx !== index);
// update just the positions of the state.
// try to create paramsUdpated yourself.
this.setState({params: paramsUdpated});
};
Second: In render I would not pass callback to props, just the name of the function and use prop itemIndex to get the index of the positions array in ItemRow component.
{this.state.params.invoice.positions.map(function(item,index){
return (<ItemRow key={index} itemIndex={index} removeProductRow={this.removeProductRow}/>)}
Working example of my idea: https://codesandbox.io/s/priceless-sun-tb76r

Categories