השוואת פתרונות בקורס ריאקט

מעולה.

יש גם הרבה שאוהבים את כתיב החץ (שקול לגמרי ל bind שביצעת ב constructor):

  textChange = (e) => {
    this.setState({text:e.target.value});
  }
לייק 1

ועוד דבר- לאחרונה נהיה אופנתי להעביר פונקציה ל setState במקום אוביקט, כלומר לכתוב:

textChange = (e) => {
  const text = e.target.value;
  this.setState((oldState) => ({ text }));
}
לייק 1

פתרון תרגיל 2 שלי. `
ינון - קבלתי את הערותייך :slight_smile:
דבר אחד מוזר שלא עבד לי, ניסיתי להחליף את המחלקה Time לפונקציה, נראה פשוט על פנוי אך זה לא עבד.

class Time extends React.Component{
    
  render()
  {
    return <span><h3>{this.props.name}</h3><input name={this.props.name} type="text" value={this.props.value} onChange={this.props.changed} type="number"/></span>;
  }
}

/*function Time(props)
{
  return <span><h3>{this.props.name}</h3><input name={this.props.name} type="text" value={this.props.value} onChange={this.props.changed} type="number"/></span>;
}*/

class App extends React.Component{
  constructor(props)
  {
    super(props);
    
    this.state = {hourValue : 1};
  }
  
  changed = (e) =>
  {    
    const val = e.target.value;
    
    if (e.target.name=="hours")
      {
        this.setState((prevState,value) => ({hourValue:val}));
      }
    else if (e.target.name=="minutes")
      {
        this.setState((prevState,value) => ({hourValue:val/60}));
      }
    else
      {
        this.setState((prevState,value) => ({hourValue:val/360}));
      }
  }
  
  render()
  {
    return <div>
              <div><Time name="hours"   value={this.state.hourValue}     changed={this.changed}/></div>
              <div><Time name="minutes" value={this.state.hourValue*60}  changed={this.changed}/></div>
              <div><Time name="seconds" value={this.state.hourValue*360} changed={this.changed}/></div>
           </div>;
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

זה לא עבד כי בתוך גוף הפונקציה השתמשת ב this.props במקום ב props (תזכור שאין this בפונקציה)

בדרך כלל כדאי להתחיל את הפונקציה render עם הכרזה של כל המשתנים, ואז לא צריך לחפש בגוף הפונקציה ולהחליף. למשל:

render()
{
  const {name, value, changed} = this.props;
  return (
      <span>
        <h3>{name}</h3>
        <input
          name={name}
          type="text"
          value={value}
          onChange={changed}
          type="number"
        />
      </span>
    );
}

כלומר שבתוך גוף הפונקציה לא יופיע this, גם אם בנית אותה כ class.

נראה מעולה בכל מקרה,
אישית הייתי מגדיר 4 פונקציות במקום ה if/else שלך אבל זה עניין של טעם

לייק 1

פתרון תרגיל 3 שלי.
ינון, מסכים עם הערותייך.

class App extends React.Component
{
  constructor(props)
  {
    super(props);
    
    this.num = Math.floor((Math.random() * 1000) + 1);
    
    this.state = {result: 'please guess a number'};
  }
  
  valChanged = (e) => {
    
    const targetValue = e.target.value;
    
    if (targetValue == this.num)
    {
        this.setState({result:'Got it !'});
        return;
    }
    
    // 20% lie
    const shouldLie = ((Math.floor((Math.random() * 5) + 1)) % 5 == 0);

    if (shouldLie)
    {
      const res = (Math.floor((Math.random() * 2) + 1)) % 2 ? 'high - lie' : 'low - lie';
      this.setState({result:res});
    }
    else
    {
      if (targetValue > this.num){
        this.setState({result:'high'});
      }
      else
        {
          this.setState({result:'low'});
        }
    }
  }
  
  render()
  {
    return <div>
              <h3>My random num: {this.num}</h3>
              <div><input type="number" onChange={this.valChanged}></input></div>
              <h3>{this.state.result}</h3>
          </div>;
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

יפה. עכשיו נסה לשפר את הקוד:

  1. תפריד את כל הלוגיקה של המשחק לקלאס נפרד שלא קשור לריאקט. הפקד יקבל את אובייקט הלוגיקה וישתמש בו (כך שיוגדרו שני קלאסים בפיתרון)

  2. לא כדאי לשמור טקסטים בסטייט. תכל׳ס יכולים להיות שם רק שלושה ערכים. עדיף לשמור בסטייט איזשהו מזהה (למשל מספר) ולכתוב את הטקסטים עצמם רק ב render

ככה יהיה יותר קל בעתיד למצוא ולעדכן טקסטים

תיקון תרגיל 3: `

function Strategy(currentValue, originNumber)
{
  let stat;

  if (currentValue == originNumber)
    {
      return 1;
    }
    
    const shouldLie = ((Math.floor((Math.random() * 5) + 1)) % 5 == 0);

    if (shouldLie)
    {
      stat = (Math.floor((Math.random() * 2) + 1)) % 2 ? 2 : 3;
    }
    else
    {
      if (currentValue > originNumber){
        stat=4;
      }
      else
        {
          stat=5;
        }
    }
  
  return stat;
}

class App extends React.Component
{
  constructor(props)
  {
    super(props);
    
    this.num = Math.floor((Math.random() * 1000) + 1);
    this.logic = props.logic;
    this.state = {result: 'please guess a number'};
  }
  
  valChanged = (e) => {
        
    const res = this.logic(e.target.value, this.num);
    this.setState({result:res});
  }
  
  render()
  {
    return <div>
              <h3>My random num: {this.num}</h3>
              <div><input type="number" onChange={this.valChanged}></input></div>
              {this.state.result == 1 && <h3>Got it</h3>}
              {this.state.result == 2 && <h3>high - lie</h3>}
              {this.state.result == 3 && <h3>low - lie</h3>}
              {this.state.result == 4 && <h3>high</h3>}
              {this.state.result == 5 && <h3>low</h3>}
          </div>;
  }
}

ReactDOM.render(<App logic={Strategy}/>, document.getElementById('root'));

הרבה יותר טוב. אישית הייתי מאחסן את num גם כן בתוך Strategy.

דבר נוסף שווה להשתמש בקבועים כדי לשפר קריאות. במקום 1, 2, 3, 4 ו-5 נסה:

let results = {
  BINGO: 1,
  TOO_HIGH: 2,
  TOO_LOW: 3,
};

ובקוד הפקד הייתי מוציא את הבדיקה לפונקציה נפרדת כדי לקבל:

  render()
  {
    return <div>
              <h3>My random num: {this.num}</h3>
              <div><input type="number" onChange={this.valChanged}></input></div>
              <h3>{this.resultText(this.state.result)}</h3>
          </div>;
  }

ויום אחד בעתיד הרחוק תוכל לנהל את כל הטקסטים בנפרד למשל כמו שמתואר כאן

לייק 1