In the code below, I am trying to run {this.renderCost(data,'mina')} with react js. I would like to obtain the minimum value of total using the code below, but total of an object that value of nameis Equal to for example mina(or other name because it will be changed).
I tried the following :
Firstly push the value of total using indents.push(elem.total), the expected output for this part is [2000,1000] and then get minimum value of array by Math.min(...indents),the expected output for this part is [1000] but the function doesn't work.
const data = [
{
"obj": {
"no": "1",
"info": [
{
"name": "maya"
},
{
"name": "mina"
}
],
"total":"2000"
}
},
{
"obj": {
"no": "2",
"info": [
{
"name": "maya"
}
],
"total":"1000"
}
},
{
"obj": {
"no": "3",
"info": [
{
"name": "mina"
},
{
"name": "Mike"
}
],
"total":"1000"
}
}
]
renderCost(data,name){
let indents = [];
data.map((elem) => {
this.renderTotal(elem,name,indents)
})
}
renderTotal(elem,name,indents){
for(let i = 0 ; i < elem.info.length;i++){
if (elem.info[i].name == name){
indents.push(elem.total)
}
return (
Math.min(...indents)
)
}
}
The data structure you're working with isn't ideal for this particular search however you can get to your answer with the following:
const minTotalByName = (data, name) => {
const totals = data
.filter(x =>
x.obj.info.find(y => y.name === name)
).map(x => x.obj.total);
return Math.min(...totals);
}
const min = minTotalByName(data, "mina"); // 1000
To find the min value for the name you can use below code:
const { useState } = React;
function App() {
const [name, setName] = useState("");
const filtered = data
.filter(obj => obj.obj.info.some(n => n.name === name))
.map(obj => Number(obj.obj.total));
const min = filtered.length !== 0 ? Math.min(...filtered) : "";
return (
<div>
<input onChange={(e) => setName(e.target.value)} />
<div>The result is: {min}</div>
</div>
);
}
const data = [
{
obj: {
no: "1",
info: [ { name: "maya" }, { name: "mina" } ],
total: "2000"
}
},
{
obj: {
no: "2",
info: [ { name: "maya" } ],
total: "1000"
}
},
{
obj: {
no: "3",
info: [ { name: "maya" }, { name: "Mike" } ],
total: "1000"
}
}
];
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Related
I have an array (myArray), stored like so (in firebase):
[
{
"id": "1",
"Category": "Hardware",
"Name": "Xtreme"
},
{
"id": "123",
"Category": "Software",
"Name": "Obsolete"
},
{
"id": "12345",
"Category": "Software",
"Name": "V1"
},
{
"id": "1234567",
"Category": "Hardware",
"Name": "CPU"
}
]
I am using the following code:
const sorterAR = [];
myArray.forEach((item) => {
let cat = sorterAR.find(
(cat) => cat.id === item.id
);
if (!cat) {
cat = {
id: item.id,
Category: item.Category,
items: [],
};
sorterAR.push(cat);
}
cat.items.push(item);
});
And then displaying like so:
<div className="App">
{sorterAR.map((cat) => (
<>
<div>
<b>{cat.Category}</b>
</div>
<ul>
{cat.items.map((item) => (
<li>{item.Name}</li>
))}
</ul>
</>
))}
</div>
This works in that it produces an output like:
**Hardware**
Xtreme
**Hardware**
CPU
**Software**
Obsolete
**Software**
V1
How do I alter this to produce the following output:
**Hardware**
Xtreme
CPU
**Software**
Obsolete
V1
So that it displays the category name and then all the items in that category, and then moves to the next one and so forth?
I assumed that order doesn't matter if Hardware or Software should come first.
First I categorized the array into an object of Category objects using Array.prototype.reduce().
From the resultant object you can build the JSX
var data1 = [
{
id: '1',
Category: 'Hardware',
Name: 'Xtreme',
},
{
id: '123',
Category: 'Software',
Name: 'Obsolete',
},
{
id: '12345',
Category: 'Software',
Name: 'V1',
},
{
id: '1234567',
Category: 'Hardware',
Name: 'CPU',
},
];
const categorizedData = data1.reduce((acc, curr) => {
const { id, Category, Name } = curr;
if (!acc[Category]) {
acc[Category] = {
items: [],
};
}
acc[Category].items.push(Name);
return acc;
}, {});
console.log(categorizedData);
Object.keys(categorizedData).map((key, index) => {
console.log(`Category: ${key}`);
categorizedData[key].items.map((item, index) =>
console.log(`Item ${index}: ${item}`)
);
});
I am trying to add data grouping by the unit name for showing functionality
const [allData , setAllData]= useState([{'unit':'' , data:[]}])
useEffect(async () => {
await axios.get(`${BACKEND_URL}/data`).then(res => {
res.data.map(elem => {
setAllData(prev =>[...prev , { 'unit': elem.unitName, 'data': [elem.lessonName] }]);
});
});
}, []);
the result is duplicating the key for the subarray which is "unit" for my exampl:
[
{
"unit": "unit 1",
"data": [
"LO1"
]
},
{
"unit": "unit 2",
"data": [
"LO2"
]
},
{
"unit": "unit 3",
"data": [
"LO3"
]
},
{
"unit": "unit 1",
"data": [
"LO15"
]
}
]
Try like that, if find unique property unit rewrite data or push new element to array
useEffect(async () => {
await axios.get(`${BACKEND_URL}/data`).then(res => {
setAllData((prev) => {
let result = [...prev];
res.data.forEach(({ unitName: unit, lessonName }) => {
const index = result.findIndex((elem) => elem.unit === unit);
if (index >= 0) {
result[index].data = [...result[index].data, lessonName]
} else {
result.push({unit, data: [lessonName]});
}
});
return result;
});
});
}, []);
I'm trying to create a search based on an array of objects with react which data is in this format:
const data = [
{"category 1" : [
{
"name": "Orange",
"desc": "juice, orange, Water"
},
{
"name": "Ananas",
"desc": "juice, ananas, water"
}
]
},
{"category 2" : [
{
"name": "Banana Split",
"desc": "Banana, ice cream, chocolat, topping",
"allergens": "nuts"
},
{
"name": "Mango Sticky Rice",
"desc": "Mango, rice, milk",
"allergens": ""
}
]
}
]
I stored this data inside useState declaration to be able to render accordingly on data chnage:
const [filteredBySearch, setFilteredBySearch] = useState(data)
I have an input where we can type anything and set inside useState declaration.
Goal:
If I type in my input:
"Jui"
Output should be:
console.log(filteredBySearch)
/* output:
[
{"category 1" : [
{
"name": "Orange",
"desc": "juice, orange, Water"
},
{
"name": "Ananas",
"desc": "juice, ananas, water"
}
]
},
{"category 2" : []
}
]*/
Exemple 2:
If I type in my input:
"Orange banana"
Output should be:
console.log(filteredBySearch)
/* output: [
{"category 1" : [
{
"name": "Orange",
"desc": "juice, orange, Water"
}
]
},
{"category 2" : [
{
"name": "Banana Split",
"desc": "Banana, ice cream, chocolat, topping",
"allergens": "nuts"
}
]
}
]*/
I've try creating a new object with map and filter and set it with setFilteredBySearch, but I can't get anything, even creating this new object.
This the full component:
import Card from '../components/Card'
import React, { useState } from 'react';
export default function IndexPage({ data, search }) {
//search is the result of input value set on a useState
//Filter categoriesFoods by search
const [FilteredBySearch, setFilteredBySearch] = useState(data)
return (
<div className="main-content">
<div className="card-container">
{
FilteredBySearch.map(function(el, i) {
return (
<div key={i}>
<h2 className="category" id={Object.keys(el)}>{Object.keys(el)}</h2>
{
el[Object.keys(el)].map (function(itm,index){
return <Card key={index} infoItem={itm}/>
})
}
</div>
)
})
}
</div>
<style jsx>{`...`}</style>
</div>
)}
Any idea for me ?
Thanks a lot for your guidance!
I think this is what you are looking for. I have created below utilities for filtering as per your requirement.
const dataObj = [
{
'category 1': [
{
name: 'Orange',
desc: 'juice, orange, Water',
},
{
name: 'Ananas',
desc: 'juice, ananas, water',
},
],
},
{
'category 2': [
{
name: 'Banana Split',
desc: 'Banana, ice cream, chocolat, topping',
allergens: 'nuts',
},
{
name: 'Mango Sticky Rice',
desc: 'Mango, rice, milk',
allergens: '',
},
],
},
]
const checkIfInputMatches = (input, desc) => input.toLowerCase().split(" ").some(o => desc.toLowerCase().includes(o))
const filterByInput = (data, input) => {
let finalResult = [];
data.forEach(d => {
let keys = Object.keys(d);
let values = Object.values(d);
finalResult = [...finalResult, ...values.map((obj, index) => {
let result = obj.filter(o => checkIfInputMatches(input, o.desc))
return {[keys[index]]: result}
})]
})
return finalResult
}
console.log(filterByInput(dataObj, 'JUI'))
console.log(filterByInput(dataObj, "orange"))
console.log(filterByInput(dataObj, "rice"))
console.log(filterByInput(dataObj, "Orange banana"))
Hope this helps.
I have Items data which I am attempting to display array values sorted by cost field in costtable array when roomname is Double and type is 2.Here is my code:
Json:
{
"index": 1,
"id": "5e3961face022d16a03b1de9_1023632_1004876",
"costtable": [
{
"roomname": "Single",
"room_id": "1023632_479490,1004876_385485",
"family": [
{
"title": "adult 1",
"cost": 3.7568000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 2,
"id": "5e3961face022d16a03b1de9_1088496_1005362",
"costtable": [
{
"roomname": "Double",
"room_id": "1088496_447339,1005362_415279",
"family": [
{
"title": "adult 1",
"cost": 5.6868000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 3,
"id": "5e3961face022d16a03b1de9_1141859_1005529",
"costtable": [
{
"roomname": "Single",
"room_id": "1141859_74888,1005529_870689",
"family": [
{
"title": "adult 1",
"cost": 5.9586000,
"unit": "10",
"type": "2"
}
]
}
]
}
]
Code:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
Items: [],
library: null,
perPage: 20,
currentPage: 1,
maxPage: null,
}
}
componentDidMount() {
fetch('/json', {
method: 'GET',
})
.then(response => response.text())
.then(text => {
let Maindata = JSON.parse(text.replace(/\'/g, '"'))
let CostSort = Maindata.map(a => {
return this.renderSort(a)
})
Maindata.sort((a, b) => a.CostSort - b.CostSort);
this.setState(state => ({
...state,
Items: Maindata
}), () => {
this.reorganiseLibrary()
})
}).catch(error => console.error(error))
}
reorganiseLibrary = () => {
const { perPage, Items } = this.state;
let library = Items;
library = _.chunk(library, perPage);
this.setState({
library,
currentPage: 1,
maxPage: library.length === 0 ? 1 : library.length
});
};
renderSort(element) {
let indents = []
let lenFamilies = element.costtable.length
for (let i = 0; i < lenFamilies; i++) {
if (element.costtable[i].roomname.indexOf('Double') > -1) {
for (let j = 0; j < element.costtable[i].family.length; j++) {
if (element.costtable[i].family[j].type == 2) {
indents.push(element.costtable[i].family[j].cost)
break;
}
}
break;
}
}
return (indents)
}
// Previous Page
previousPage = event => {
this.setState({
currentPage: this.state.currentPage - 1
});
};
// Next Page
nextPage = event => {
this.setState({
currentPage: this.state.currentPage + 1
});
};
// handle per page
handlePerPage = (evt) =>
this.setState({
perPage: evt.target.value
}, () => this.reorganiseLibrary());
// handle render of library
renderLibrary = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return '';
}
return library[currentPage - 1].map((item, i) => (
<div className="item-list">
{item.index}
</div>
));
};
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div>
<div className="wrapper-data">
{this.renderLibrary()}
</div>
<div class="clr"></div>
<ul id="page-numbers">
<li className="nexprevPage">
{currentPage !== 1 && (
<button onClick={this.previousPage}><span className="fa-backward"></span></button>
)}
</li>
<li className="controlsPage active">{this.state.currentPage}</li>
<li className="restControls">...</li>
<li className="controlsPage">{this.state.maxPage}</li>
<li className="nexprevPage">
{(currentPage < maxPage) && (<button onClick={this.nextPage}><span className="fa-forward"></span></button>
)}
</li>
</ul>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('Content'));
This code does not give me any errors but displays the values in an unsorted format. How can I sort it?
New Code
Maindata.sort((a, b) => {
let lenFamilies = a.costtable.length
for (let i = 0; i < lenFamilies; i++) {
if( a.costtable[i].roomname.indexOf('Double') > -1){
for (let j = 0; j < a.costtable[i].family.length; j++) {
if( a.costtable[i].family[j].type == 2){
a.costtable[i].family[j].cost- b.costtable[i].family[j].cost
}
}
}
}
}
I do not understand the exact formula that you are using to sort, but what you are doing before the sort is wrong.
In your componentDidMount
let CostSort = Maindata.map(a => { return this.renderSort(a) })
This returns an array into a variable called CostSort and does not affect MainData in any way.
However, later on you do this.
Maindata.sort((a, b) => a.CostSort - b.CostSort);
For first iteration, this will compare Maindata[0] and Maindata[1]. Note that there is no CostSort in either of the objects and hence you are performing operation of undefined - undefined which is NaN. Therefore no sorting happens.
I would suggest you use only the sort function and do your comparison between two values there.
Maindata.sort((a, b) => {
// Do your calculation here
if(a should be before b) {
return -1;
} else {
return 1;
}
}
P.S The convention for variable in js is camelCase and not PascalCase. So, Maindata should he mainData.
EDIT:
Here is a simple sort implementation which works for the above case, you can expand on it according to your full use case.
Maindata.sort((a, b) => {
let lenFamilies = a.costtable.length;
for (let i = 0; i < lenFamilies; i++) {
if (
a.costtable[i].roomname.includes("Double") &&
!b.costtable[i].roomname.includes("Double")
) {
return -1;
}
if (
!a.costtable[i].roomname.includes("Double") &&
b.costtable[i].roomname.includes("Double")
) {
return 1;
}
if (a.costtable[i].roomname.indexOf("Double") > -1) {
for (let j = 0; j < a.costtable[i].family.length; j++) {
if (a.costtable[i].family[j].type == 2) {
a.costtable[i].family[j].cost - b.costtable[i].family[j].cost;
}
}
}
}
});
Omitting the algorithms (bubble, quicksort, by inserting ...). There is possible of sorting in UI context.
Your json have:
title | cost | unit | type
What type of sort You need? (title is string (can eg. sort alphabetically), then cost, unit & type are number (ascending + descending)
It's will be helpfull - when in future You provide only neccessary piece of code.
Here it's ellegant minimalistic function responsible for asc/desc sorting.
Firstly it's need to pass the props(which You wan't to sort) to values state.
function App() {
const [ascValue, setAscValue] = useState(true);
const [values, setValues] = useState([10, 5, 12, 1, 2, 900, 602]);
function sortValues() {
const compare = ascValue ? (a, b) => a - b : (a, b) => b - a;
setValues([...values].sort(compare));
}
useEffect(() => {
sortValues();
}, [ascValue]);
return (
<div>
<h3>{ascValue.toString()}</h3>
<button onClick={() => setAscValue(!ascValue)}>Toggle Asc</button>
{values.map(v => (
<p key={v}>{v}</p>
))}
</div>
);
}
Here is sorting by cost for your object:
let text = [{
"index": 1,
"id": "5e3961face022d16a03b1de9_1023632_1004876",
"costtable": [
{
"roomname": "Single",
"room_id": "1023632_479490,1004876_385485",
"family": [
{
"title": "adult 1",
"cost": 3.7568000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 2,
"id": "5e3961face022d16a03b1de9_1088496_1005362",
"costtable": [
{
"roomname": "Double",
"room_id": "1088496_447339,1005362_415279",
"family": [
{
"title": "adult 1",
"cost": 5.6868000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 3,
"id": "5e3961face022d16a03b1de9_1141859_1005529",
"costtable": [
{
"roomname": "Single",
"room_id": "1141859_74888,1005529_870689",
"family": [
{
"title": "adult 1",
"cost": 5.9586000,
"unit": "10",
"type": "2"
}
]
}
]
}
]
const App = () =>{
const usersWithName = Object.keys(text).map(function(key) {
var user = text[key];
return user.costtable[0].family[0].cost;
});
let costArray = usersWithName
const [ascValue, setAscValue] = useState(true);
const [values, setValues] = useState(costArray);
function sortValues() {
const compare = ascValue ? (a, b) => a - b : (a, b) => b - a;
setValues([...values].sort(compare));
}
useEffect(() => {
sortValues();
}, [ascValue]);
return (
<div>
<h3>{ascValue.toString()}</h3>
<button onClick={() => setAscValue(!ascValue)}>Toggle Asc</button>
{values.map(v => (
<p key={v}>{v}</p>
))}
</div>
);
}
export default App;
I don't have idea of performance in this case + if in your json are more costtable & family it should iterate by [i] iterator.
I have array like this in react native
const data = [
{ key: 1, label: 'Service1'},
{ key: 2, label: 'Service2' },
{ key: 3, label: 'Service3' },
{ key: 4, label: 'Service4' },
{ key: 5, label: 'Service4' },
];
and json data:
"services": [
{
"id": 1,
"name": "Hotels",
},
{
"id": 2,
"name": "Embassies",
},
]
How to map id to key and name to label???
You want to fill your const data with values from JSON, correct?
Try this:
var jsonData = {
"services": [
{ "id": 1, "name": "Hotels" },
{ "id": 2, "name": "Embassies" }
]
};
var data = jsonData.services.map(function(item) {
return {
key: item.id,
label: item.name
};
});
console.log(data);
if your data like below (removed services key)
var jsonData = [
{ "id": 1, "name": "Hotels" },
{ "id": 2, "name": "Embassies" }
];
var data = jsonData.map(function(item) {
return {
key: item.id,
label: item.name
};
});
console.log(data);
i know it to much late,but i hope its helpfull for others,How to fetch the response of JSON array in react native?How to map json data with array in react native
export default class ExpenseNew extends Component {
constructor(){
super();
this.state={
PickerSelectedVal : '',
accountnameMain:[],
}
}
componentDidMount(){
var account_nam=[]
fetch('your Url', {
method: 'GET',
headers: { 'Authorization': 'Bearer ' + your token }
})
.then((response) => response.json())
.then((customerselect) => {
// alert(JSON.stringify(customerselect))
global.customerdata = JSON.stringify(customerselect)
var customername = JSON.parse(customerdata);
//alert(JSON.stringify(customername));
for (i = 0; i < customername.cus_data.length; i++) {
var dataa = customername.cus_data[i]["account_name"];
account_nam.push(dataa)
}
this.setState({accountnameMain:account_nam});
})
.done();
}
render() {
return (
<Picker
selectedValue={this.state.PickerSelectedVal}
placeholder="Select your customer"
mode="dropdown"
iosIcon={<Icon name="arrow-down" />}
onValueChange={(itemValue, itemIndex) => this.setState({PickerSelectedVal: itemValue})} >
{this.state.accountnameMain.map((item, key)=>(
<Picker.Item label={item} value={item} key={key}/>)
)}
</Picker>
)
}
}
the above example is fetch array of data from json,and map data in to dropdown/picker,i hope its helpfull for others,if you have any query, asked from me