Isaac
Isaac

Reputation: 12884

Screen doesnt re-render even props changed?

I'm currently facing a problem where the screen doesnt re-render to load the new added value to array. Even tried with componentWillReceiveProps and trigger a this.forceUpdate() manually doesn't help. The screen only show the new value when I restart the app

this.props.addNewRecord({ 
    recordDetails: { ...this.props.recordDetails, type: this.state.type },
    records: this.props.records
  });

return (
  <View>
    {
      this.props.records.map((x, i) => {
        return (
          <View style={{ flexDirection: 'row' }}>
            <Text>{`${i}: `}</Text>
            <Text>{x.id}</Text>
          </View>
        );
      })
    }
  </View>
);

const mapStateToProps = ({ account, settings, main }) => {
  const year = moment().year();
  const month = moment().format('MMM');

  return {
    records: account.records[year][month].records,
  };
};

export default connect(mapStateToProps)(SummaryScreen);

account.records has the following structure

{
  2018: {
    Jan: {
      records: [{...}, {...}]
    }
  }
}

And below is the adding record part

const addNewRecord = ({ recordDetails, records }) => {
  const year = moment(recordDetails.date).year();
  const month = moment(recordDetails.date).format('MMM');

  const newRec = {
    id: uuidv4(),
    account_id: recordDetails.account_id,
    date: recordDetails.date,
    description: recordDetails.description,
    amount: recordDetails.result,
    type: recordDetails.type
  };

  update(year, month, newRec, records);

  return {
    type: ADD_NEW_RECORD,
    payload: records
  };
};

const update = (year, month, obj, target) => {
  [year, month].reduce((r, e, i, a) => {
    if (!a[i + 1] && r[e]) {
      r[e].records.push(obj);

      if (obj.type === 'expense') r[e].totalExpenses = parseFloat(r[e].totalExpenses) + parseFloat(obj.amount);
      if (obj.type === 'income') r[e].totalIncome = parseFloat(r[e].totalIncome) + parseFloat(obj.amount);
    }
    return r[e] = (r[e] || (a[i + 1] ? {} : {
      records: [obj],
      totalExpenses: obj.type === 'expense' ? parseFloat(obj.amount) : 0,
      totalIncome: obj.type === 'income' ? parseFloat(obj.amount) : 0,
      type: obj.type
    }));
  }, target);
};

And Reducer as below:

switch (action.type) {
  case ADD_NEW_RECORD:
    return { ...state, records: action.payload };

Upvotes: 3

Views: 67

Answers (1)

Isaac
Isaac

Reputation: 12884

this.props.addNewRecord({ 
  recordDetails: { ...this.props.recordDetails, type: this.state.type },
  records: _.cloneDeep(this.props.records)//this.props.records
});

The problem is I've passed this.props.records as records which later gets mutated, and eventually old state get mutated to be the same as new state and that's why Redux unable to spot the differences.

Credits to @Y.Gherbi for spotted this flaw. Hope it helps whoever facing same issue

Upvotes: 1

Related Questions