简体   繁体   中英

Render element based on key value from JSON

Let's say I have json file,

[
    {"page":"about","title":"About","order":"0"},
    {"page":"another-test","title":"Another Test"},
    {"page":"how-to","title":"How To","order":"1"},
    {"page":"test-page","title":"Test page","order":"2"}
]

Here, you see a key order , when I map this json file, I want to render the one with less order value first. For example,

import myJSON from 'file.json'

....
myJSON.map(({ page, title }) => (
   <h1 key={page}>{title}</h1>
))
....

How can I use the order key and render the one with the less order value or ascending order?

You could sort them based on order.

myJSON.sort((a, b) => parseInt(a.order) - parseInt(b.order))

myJSON.map(({ page, title }) => (
   <h1 key={page}>{title}</h1>
))

Rahul's solution has a flaw. Any orthodox solution to this will have this same flaw.

What if the "order" property is undefined as it is in record 2 in myJSON?

{"page":"another-test","title":"Another Test"}

Then this approach will default to the 0 case (equal values). It will think the undefined value and the value it is comparing it to are equal.

Here is an example:

let myJSON = [
   {"page":"about","title":"About","order":"100"},
   {"page":"another-test","title":"Another Test"},
   {"page":"how-to","title":"How To","order":"50"},
   {"page":"test-page","title":"Test page","order":"10"}
]

function myCompareFunc( a, b ) {
  // if a.order or b.order is undefined this is false
  if ( a.order < b.order ){
    return -1; 
  }
  // if a.order or b.order is undefined this is false
  if ( a.order > b.order ){
    return 1;
  }
  // will default to this
  return 0; 
}
myJSON.sort(myCompareFunc);

The records that are before the record with the undefined "order" prop will not be sorted against the records that are after. So record 1 and 2 in the json above will keep their places and only record 3 and 4 will be sorted properly against each other and will switch places. Result will be:

   {"page":"about","title":"About","order":"100"},
   {"page":"another-test","title":"Another Test"},
   {"page":"test-page","title":"Test page","order":"10"},
   {"page":"how-to","title":"How To","order":"50"}

That is not quite sorter is it?

How to fix it? One way is to add this at the start of the compare function:

  if ( !a.order ){
    return -1;
  }

That will sort all records with undefined "order" prop to the beginning of the array and will not meddle with the records that have a defined "order" prop.

That structure could be optimised for quicker access.

I'd try to denormalise it a bit and create something like the below example. This enables you to use Object.keys() to quickly get all the page ids.

pageData.json

{
  "about": {
    "id": "about",
    "title": "About",
    "order":100
  },
  "another-test": {
    "id": "another-test",
    "title": "Another Test"
  }
}

The solution to the inital query of finding out which pages had order would be

import pageData from '...'

const pageKeys = Object.keys(pageData);
const pagesThatHaveOrder = pageKeys.filter(key => !pageData[key].order)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM