שטויות שלא כדאי לעשות עם React-Redux

22/09/2016

פוסט זה כולל טיפ קצר לעבודה עם React. אם אתם רוצים ללמוד איתי ריאקט מההתחלה ובצורה מקצועית תשמחו לשמוע שבניתי קורס מלא הכולל עשרות שיעורי וידאו והמון תרגול בו לומדים ריאקט מההתחלה ועד לנושאים המתקדמים.
לפרטים נוספים והרשמה בקרו בדף קורס ריאקט כאן באתר.
 

את הבאג הבא לקח לי יותר מדי זמן למצוא, נראה אם תצליחו להיות מהירים יותר.

1. קטע הקוד הרלוונטי

זה הקטע הרלוונטי מתוך הקוד:

function mapStatusStateToProps(state) {
  return {
    success: state.get('val') > 50,
  }  
}

var Status = connect(mapStatusStateToProps)(React.createClass({
  render: function() {
    return <div>
      <p>Success: {this.props.success ? 'YES!' : 'no...'}</p>
    </div>
  }
}));


function mapAppStateToProps(state) {
  return {
    val: state.get('val'),
  }
}

var App = connect(mapAppStateToProps)(React.createClass({
  render: function() {
    return <div>
      <p>Value: {this.props.val}</p>
      <button onClick={() => {this.props.dispatch(actions.randomize())}}>Rand</button>
      <Status success={this.props.val > 10} />
    </div>
  }
}));

את התוכנית המלאה רצה אפשר למצוא בקודפן הבא (וגם לשחק עם זה ולראות את הטעות בפעולה):
http://codepen.io/ynonp/pen/wzomGw

והשאלה: באיזה מקרים הפקד Status ידפיס Success: YES ?

2. מה גורם לבלבול

קל לראות שערך המשתנה success מועבר לפקד פעמיים: פעם אחת דרך react-redux ופעם שניה בתור Property מהפקד שמכיל אותו. השאלה איזה מקור מקבל קדימות? כלומר בהנחה שערכו של val הוא 30, האם החישוב יגיע מ App ואז נקבל YES או מ connect ואז נקבל no?

מאחר וגם העברת המידע דרך הפקד המכיל עוברת דרך react-redux, כדאי להתבונן בקוד הספריה ולראות איך ה properties מאוחדים. בקובץ src/components/connect נוכל למצוא את הגדרת הפונקציה הבאה:

const defaultMergeProps = (stateProps, dispatchProps, parentProps) => ({
  ...parentProps,
  ...stateProps,
  ...dispatchProps
})

וכאן גם טמון ההסבר לבאג. כשאנחנו מעבירים מאפיין עם אותו שם משני מקומות שונים, הערך מ mapStateToProps מקבל עדיפות ודורס את הערך שעבר מהמיכל. זו החלטה הגיונית אבל היה נחמד אם React-Redux היתה מזהה את הכפילות ומודיעה על כך, לפחות במצב פיתוח.