简体   繁体   中英

Reactjs- Map and Filter JSON data with props

I'm stuck on an issue that shouldn't keep me stuck. Can't figure out how to get this done…

I have a db.json that looks like this:

{
   "applicants": [{
     "id": 1,
     "firstName": "John",
     "lastName": "Doe",
     "email": "john.doe@example.com",
     "coverLetter": "Aliquam ut nunc eu augue volutpat porta ullamcorper sed."
  }, {
     "id": 2,
     "firstName": "Erica",
     "lastName": "Hayfied",
     "email": "erica@example.com",
     "coverLetter": "Pellentesque habitant morbi tristique senectus."
  }, {
     "id": 3,
     "firstName": "Lex",
     "lastName": "Luther",
     "email": "lex@example.com",
     "coverLetter": "Phasellus fermentum, neque nec posuere hendrerit."
  }, {
     "id": 4,
     "firstName": "Bruce",
     "lastName": "Wayne",
     "email": "bruce@example.com",
     "coverLetter": "Vestibulum varius purus non convallis ultricies."
  }, {
     "id": 5,
     "firstName": "Peter",
     "lastName": "Parker",
     "email": "peter@example.com",
     "coverLetter": "Aenean faucibus augue id justo viverra, eget."
  }, {
     "id": 6,
     "firstName": "Diana",
     "lastName": "Prince",
     "email": "diana@prince.com",
     "coverLetter": "Nam dolor urna, imperdiet ac ipsum quis, aliquet laoreet."
  }],

    "skills": [{
     "id": 1,
     "description": "PHP",
     "experienceInYears": 3,
     "applicantId": 1
  }, {
     "id": 2,
     "description": "JavaScript",
     "experienceInYears": 3,
     "applicantId": 1
  }, {
     "id": 3,
     "description": "Objective-C",
     "experienceInYears": 10,
     "applicantId": 1
  }, {
     "id": 4,
     "description": "Objective-C",
     "experienceInYears": "3 Years",
     "applicantId": 2
  }, {
     "id": 5,
     "description": "Karate",
     "experienceInYears": 20,
     "applicantId": 2
  }, {
     "id": 6,
     "description": "Ruby",
     "experienceInYears": 20,
     "applicantId": 4
  }, {
     "id": 7,
     "description": "Apothecary",
     "experienceInYears": 15,
     "applicantId": 4
  }, {
     "id": 8,
     "description": "Speak German",
     "experienceInYears": 5,
     "applicantId": 4
  }, {
     "id": 9,
     "description": "Swim",
     "experienceInYears": 5,
     "applicantId": 4
  }, {
     "id": 10,
     "description": "Run",
     "experienceInYears": 5,
     "applicantId": 4
  },  {
     "id": 11,
     "description": "Writer",
     "experienceInYears": 5,
     "applicantId": 4
  }, {
     "id": 12,
     "description": "Fighting Crime",
     "experienceInYears": 33,
     "applicantId": 4
  }, {
     "id": 13,
     "description": "Weaving Webs",
     "experienceInYears": 3,
     "applicantId": 5
  }, {
     "id": 14,
     "description": "Spidey Senses",
     "experienceInYears": 3,
     "applicantId": 5
  }, {
     "id": 15,
     "description": "Olympic Lifting",
     "experienceInYears": 3,
     "applicantId": 6
  }]
}

Consider an applicant's top skill to be the skill with the most years of experience.

For example if Bob has 3 years of experience with PHP, and 5 years of experience with Objective-C, then Bob's top skill is Objective-C.

I want to display each applicants' top skill in the list of applicants within the card body. Like this . More specifically, within the ApplicantRow component using props.

Here is the component structure:

ApplicantRow.js

import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';

import { get } from 'lodash';

import { Card, CardBody, CardFooter } from '../card';

class ApplicantRow extends Component {
 render() {
  return (
   <Card>
    <CardBody>
      <Text style={styles.name}>
        {this.props.applicant.firstName} {}
        {this.props.applicant.lastName}
      </Text>

      <Text style={styles.coverLetter}>
        {this.props.applicant.coverLetter}
      </Text>
    </CardBody>
    <CardFooter style={styles.row}>
      <View style={styles.col}>
        <Text style={styles.label}>SKILL COUNT</Text>
        <Text style={styles.skill}>
          {get(this.props.applicant, 'skills.length', 0)}
        </Text>
      </View>

      <View style={styles.col}>
        <Text style={styles.label}>TOP SKILL</Text>
        <Text style={styles.skill}>
          {/* TOP SKILL SHOULD BE SHOWN HERE */}
        </Text>
      </View>

    </CardFooter>
  </Card>
  );
 }
}

export { ApplicantRow as default };

ApplicantsList.js

import React, { Component, PropTypes } from 'react';
import { ActivityIndicator, Button, ListView, StyleSheet, Text, View } from 'react-native';

import { Card, CardBody, CardFooter, CardHeader } from '../card';
import ApplicantRow from './ApplicantRow';

class ApplicantsList extends Component {
 constructor(props) {
  super(props);

  this.renderRow = this.renderRow.bind(this);
  this.renderHeader = this.renderHeader.bind(this);
}

renderRow(applicant) {
 return this.props.isFetching ? null : <ApplicantRow applicant={applicant} />;
}

renderHeader() {
 return (
  <Card>
    <CardHeader>
      <Text style={styles.cardHeading}>Applicant Management</Text>
    </CardHeader>

    <CardBody>
      <Text style={styles.cardText}>
        Here at ACME we got a large amount of applicants. Easily view, edit, remove, and {}
        add applicants from this screen!
      </Text>
    </CardBody>

    <CardFooter>
      <Button
        title={`Sort Applicants (Order: ${this.props.sortOrder})`}
        onPress={this.props.onSortPress}
      />
    </CardFooter>
  </Card>
);
}

 render() {
  return (
   <View style={styles.scene}>
    <ListView
      dataSource={this.props.dataSource}
      renderRow={this.renderRow.bind(this)}
      renderHeader={this.renderHeader}
      enableEmptySections
    />

    {this.props.isFetching && <ActivityIndicator style={styles.centered} size="large" />}
  </View>
 );
 }
}

ApplicantsList.propTypes = {
 dataSource: PropTypes.instanceOf(ListView.DataSource).isRequired,

 isFetching: PropTypes.bool,

 onSortPress: PropTypes.func,
};

export { ApplicantsList as default };

How would you do this in basic JS? Array filter? Array map? Array reduce? None of these? Any help would be much appreciated!

You could perform a .filter and .reduce :

const getTopSkillForApplicant = (applicantId, allSkills) => {
    const skillsForApplicant = allSkills.filter(skill => skill.applicantId === applicantId);
    const bestSkillForApplicant = skillsForApplicant.reduce((prev, skill) => {
        return prev.experienceInYears > skill.experienceInYears ? prev : skill;
    }, []);

    return bestSkillForApplicant;
}

Working JSBin: http://jsbin.com/jenewal/edit?js,console

By-the-by, I'd recommend consideration to normalize the data. There's an excellent library called normalizr which allows you to do this easily.

To sort json arrays of an objects in java script you can use sortOn method. It's the fastest way for sorting.

var sortedApplications = applicants.sortOn("experienceInYear");

http://upshots.org/javascript/array-prototype-sorton-for-javascript

And the fastest way to find something in array is to use indexOf method of simple arrat arrays like array of strings. Otherwise you should write a loop to find your matched object elements.

But I wrote you the simple way here:

var indexOfTargetedAge = ageArray.indexOf (5);
applicants[indexOfTargetedAge]// is the item that you needed

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