title: Performance drop when updating state
body: <p>I'm building react-native app, but my problem is linked with React itself.</p>
  
  <p>It's an app that connects to external JSON, fetches data, and creates react component for each of item in that JSON data, so it's like 70 child components inside 1 wrapper. App is also using Navigator and phone storage but that's a part of the question.</p>
  
  <p>To visualize:
  Parent component (People) has methods to operate on a DB, it fetches data, creates component for each of item in array and exposes methods to child components (Person). Each person has a "add to favourites" button, this is a method updating empty star to full one (conditional rendering) if clicked, updates state of component and whenever local state has been changed it fires parents component to update it's state - and from there parent's component saves all data to DB. So I've made a link to synchronize Child's State -> Parent's State -> Local DB (phone's memory).</p>
  
  <p>Problem is, it's quite slow when updating parent's state. It freezes for 1-1.5 sec. but it's all cool if I remove method to update parent's state (I've marked that in example attached).</p>
  
  <p>Question 1: How to refactor this code to fix performance issue when updating parent's (People's state)?
  Question 2: I'm open to any other suggestions and lessons how to improve quality of my code.</p>
  
  <p>Here's a link to visualize my code, I've just removed few non-relevant methods and styles.</p>
  
  <p><a href="https://jsfiddle.net/xvgfx90q/" rel="nofollow noreferrer">https://jsfiddle.net/xvgfx90q/</a></p>
  
  <pre><code>class People extends React.Component {
  
      constructor() {
          super();
  
          this.state = {
              peopleData: [],
              database: {}
          }
      }
  
      componentDidMount() {
          this.fetchApi(); 
          this.syncDatabase();
      }
  
      // function that connects to external JSON file and parses it
      fetchApi() {... it sets peopleData state after promise has been resolved}
  
      // function called from PersonSection to pass it's state and update main state of People
      syncStates(data) {
          const newState = this.state;
          newState.database[data.id] = data;
          this.setState(newState); // &lt;-- !! PERFORMANCE DROP HERE !!
          this.saveDatabase();
      }
  
      // connects to phone's DB and updates state with result of promise
      async syncDatabase() {
          AsyncStorage.getItem(this.state.DBKey).then((data) =&gt; {
              let newState = {};
              newState.database = JSON.parse(data);
              this.setState(newState);
          }).catch((error) =&gt; {
              return error;
          })
      }
  
      // saves current state to DB
      async saveDatabase() {
          AsyncStorage.setItem(this.state.DBKey, JSON.stringify(this.state.database));
      }
  
  
      renderTeams() {
          return Object.keys(this.state.peopleData).map((team) =&gt; {
              return (
                  &lt;TeamSection key={team} teamName={team} membersList={this.state.peopleData[team]}&gt;
                      {this.renderPeople(team)}
                  &lt;/TeamSection&gt;
              )
          })
      }
  
      renderPeople(team) {
          return this.state.peopleData[team].map((people) =&gt; {
              return (
                  &lt;PersonSection
                      key={people.id}
                      data={people}
                      database={_.has(this.state.database, people.id) ? this.state.database[people.id] : false}
                      navigator={this.props.navigator}
                      syncStates={this.syncStates.bind(this)}
                   /&gt;
              )
          })
      }
  
      render() {
          return (
              &lt;ScrollView style={styles.wrapper}&gt;
                  &lt;Options filterPeople={this.filterPeople.bind(this)} /&gt;
                  {this.renderTeams()}
              &lt;/ScrollView&gt;
          )
      }
  }
  
  class PersonSection extends Component {
  
      constructor(props) {
          super(props);
  
          this.state = {
              database: {
                  id: this.props.data.id,
                  name: this.props.data.name,
                  favourites: this.props.database.favourites
              }
          }
      }
  
      // updates components state and sends it to parent component
      toggleFavourites() {
          const newState = this.state.database;
          newState.favourites = !newState.favourites;
          this.setState(newState);
          this.props.syncStates(this.state.database);
      }
  
      render () {
          return (
              &lt;View&gt;
                  &lt;View&gt;
                      &lt;View&gt;
                          &lt;Text&gt;{this.props.data.name}&lt;/Text&gt;
                          &lt;Text&gt;{this.props.data.position}&lt;/Text&gt;
                          &lt;Text&gt;{this.props.data.ext}&lt;/Text&gt;
                      &lt;/View&gt;
                  &lt;View&gt;
                      &lt;TouchableOpacity onPress={() =&gt; this.toggleFavourites()}&gt;
                      { this.state.database.favourites
                          ? &lt;Icon name="ios-star" size={36} color="#DAA520" /&gt;
                          : &lt;Icon name="ios-star-outline" size={36} color="#DAA520" /&gt;}
                      &lt;/TouchableOpacity&gt;
                  &lt;/View&gt;
              &lt;/View&gt;
          &lt;/View&gt;
          )
      }
  
  };
  
  export default PersonSection;
  
  React.render(&lt;People /&gt;, document.getElementById('app'));`
  </code></pre>