הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

צעדים ראשונים עם react-testing-library

31/08/2020

ספריית react-testing-library היא היום הדרך המקובלת לכתוב בדיקות ליישומי ריאקט. קוד rtl נוצר כל פעם שאנחנו בונים אפליקציה חדשה עם create-react-app וגם הסקריפטים הדרושים להריץ אותו. בואו נראה איך להתחיל להשתמש בספריה כדי לכתוב בדיקות ולמה זה כדאי.

המשך קריאה

כמה טיפים לגבי פיצול Reducer ב Redux

16/08/2020

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

For any meaningful application, putting all your update logic into a single reducer function is quickly going to become unmaintainable.

אז אחרי משפט כזה ברור למה רבים מאיתנו בכלל מתחילים מלחשוב "איזה Reducers אני צריך?" אפילו לפני שמתחילים לכתוב את שורת הקוד הראשונה של ה Reducer הראשון. הרי אם בשביל יישום אמיתי אני אהיה חייב לשבור אותו, עדיף לבנות את המנגנון נכון מההתחלה.

אבל הניואנס במשפט שקל לפספס אותו הוא שיש יותר מדרך אחת לפצל Reducer. השיטה הפופולרית של combineReducers (שנקראת בתיעוד Slice Reducer) היא רק אחת מהן.

בפוסט זה נעבור בקצרה על מספר שיטות לפיצול ונראה מתי כדאי להשתמש בכל שיטה.

המשך קריאה

דוגמת ריפקטורינג של טפסים ב React

14/06/2020

אחת השאלות שחוזרות על עצמן בעבודה עם ריאקט היא איך להתמודד עם טפסים. גישה אחת היא לנהל את כל המידע שבטופס מחוץ ל State, ואז לקרוא את המידע משדות ה input רק כשצריכים אותו. היום אני רוצה להראות גישה שניה בה המידע כולו נשמר בסטייט ומעודכן עם כל שינוי בערכי ה input.

המשך קריאה

תחליף פשוט ל create-react-app

03/06/2020

למה כלים צריכים להיות כל כך מסובכים? התשובה פשוטה: כל פעם שיוצא כלי חדש הוא מנסה להיות יותר פשוט מזה שבא לפניו (אנחנו ה create-react-app החדש. אצלנו אין פיצ'רים והכל פשוט עובד), ואז אנשים מתחילים להשתמש בו ומבקשים כל מיני פיצ'רים, לאט לאט הכלי החדש מסתבך וחזרנו להתחלה כדי לפתח כלי חדש (ללא פיצ'רים - הכל פשוט עובד).

בקיצור הכלי החדש האהוב עליי בימים אלה נקרא nano-react-app והוא תחליף ממש פשוט ל create-react-app (קיבל כבר מעל 300 כוכבים בגיטהאב). וזה מצחיק כי הוא באמת לא עושה כלום - כלומר הוא עושה קצת. הוא לוקח טמפלייט מהאינטרנט ליישום ריאקט JavaScript או TypeScript, משנה קצת את התוכן בקבצים וזה בערך כל הסיפור.

בניגוד ל create-react-app הוא לא מבטיח לכם פרויקט עם כל התוספים וכל הספריות מחוברות במקום אלא בדיוק להיפך. אתם תקבלו קומפוננטה קטנה (ב JavaScript או ב TypeScript) ותמשיכו לבד. בדיקות? הצחקתם אותו. סרביס וורקר? למי יש כח לזה. טמפלייטס מורכבים עם Redux או MobX? עזבו, תכתבו לבד.

ועכשיו רק נשאר להבין: אם כל מה שצריך זה לשים כמה קבצים בתיקיה, בשביל מה היינו צריכים את הכלי הזה מלכתחילה?

שני מסלולי בוטקמפ חדשים

25/05/2020

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

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

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

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

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

שני המסלולים לא מיועדים למי שרוצה "ללמוד ריאקט תוך כדי שינה", אלא למי שרוצה לשבת ללמוד דרך התמודדות עם בעיות ובליווי מנחה וקבוצת חברים. אני חושב ששניהם יהיו מהנים מאוד. עכשיו לפרטים הטכניים:

מסלול בוטקמפ ללימוד ריאקט ייפתח בתאריך 14.06.2020 למשך שלושה שבועות. מפגשי העבודה יתקיימו בימי ראשון ורביעי בין השעות 9:00 ל-11:00 בבוקר בתאריכים: 14/06, 17/06, 21/06, 24/06, 28/06, 01/07. מחיר הקורס 970 ש"ח וזה כולל חודש מנוי לתקופה של הקורס (אם אתם כבר מנויים החודש הזה יתווסף לכם אוטומטית לתקופת המנוי). הצטרפות לבוטקמפ בקישור: https://www.tocode.co.il/quickjoin2?term=15.

מסלול בוטקמפ ללימוד פייתון יפתח בתאריך 14.06.2020 למשך שלושה שבועות. מפגשי העבודה יתקיימו בימי ראשון ורביעי בין השעות 13:00 ל-15:00 בצהריים בתאריכים: 14/06, 17/06, 21/06, 24/06, 28/06, 01/07. מחיר הקורס 970 ש"ח וזה כולל חודש מנוי לתקופה של הקורס (אם אתם כבר מנויים החודש מתווסף אוטומטית לתקופת המנוי). הצטרפות לבוטקמפ פייתון בקישור: https://www.tocode.co.il/quickjoin2?term=16.

מוזמנים לשלוח מייל או להשאיר הודעה באתר לכל שאלה.

ריאקט ו SVG הם שילוב מעולה

06/04/2020

אחת הטכנולוגיות הנשכחות של פיתוח Web היא SVG. איכשהו כש Canvas יצאה היא הצליחה לעשות המון רעש, וכמובן ש WebGL היה מלהיב, אבל SVG? זה לא הדבר ההוא שדומה ל XML?. אז כן ולא. תקן SVG יצא לראשונה ב 2001 והשילוב בינו לבין דפדפנים ידע עליות ומורדות לאורך השנים, אבל בשנים האחרונות התמיכה ב SVG בדפדפנים ובספריות פיתוח היא מאוד יציבה ו SVG יכול לתת לכם פיתרון אמין ומהיר להצגה של נתונים בצורה ויזואלית.

בגלל ש SVG נראה כמו אלמנטים רגילים ב DOM אנחנו יכולים ליצור SVG מתוך ריאקט בדיוק כמו שהיינו יוצרים אלמנט רגיל. הקוד ריאקט הבא למשל מצייר מעגל:

function App(props) {
  return (
    <div>
      <svg>
        <circle cx="100" cy="100" r="40" />
      </svg>
    </div>
  )
}

אנחנו יכולים לעצב את המעגל מתוך CSS רגיל לגמרי כמו שהיינו מעצבים אלמנטים ב HTML. לדוגמא ה CSS כאן יהפוך את העיגול לדגל יפן:

svg {
  background: white;
  border: 1px solid black;;
}

circle {
  fill: red;
}

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

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

שילוב קומפוננטות SVG ביישום לא דורש שום ספריה חיצונית, נתמך בכל הדפדפנים ומאפשר להוסיף בקלות צורות מתוחכמות יותר מדברים שהיינו מוצאים בדרך כלל ב CSS.

איך להפוך Class Component ל Function Component ב React

24/01/2020

למרות שאין בעיה להמשיך לעבוד עם Class Components, קורה לפעמים שנמצא דוגמא ברשת של Class Component ונעדיף להפוך אותה ל Function Component לפני שמשלבים אותה ביישום שלנו.

כך לדוגמא עם הספריה jsoneditor שנותנת ממשק וובי פשוט לעריכת קבצי JSON. הספריה עצמה לא כתובה בריאקט אבל יחד עם הספריה יש קובץ דוגמא בריאקט שמראה איך להשתמש בה. תיקיית הדוגמא נמצאת בגיטהאב בקישור:

https://github.com/josdejong/jsoneditor/tree/develop/examples/react_demo

והקובץ המרכזי ממנה הוא הפקד הבא:

import React, {Component} from 'react';

import JSONEditor from 'jsoneditor';
import 'jsoneditor/dist/jsoneditor.css';

import './JSONEditorDemo.css';

export default class JSONEditorDemo extends Component {
  componentDidMount () {
    const options = {
      mode: 'tree',
      onChangeJSON: this.props.onChangeJSON
    };

    this.jsoneditor = new JSONEditor(this.container, options);
    this.jsoneditor.set(this.props.json);
  }

  componentWillUnmount () {
    if (this.jsoneditor) {
      this.jsoneditor.destroy();
    }
  }

  componentDidUpdate() {
    this.jsoneditor.update(this.props.json);
  }

  render() {
    return (
        <div className="jsoneditor-react-container" ref={elem => this.container = elem} />
    );
  }
}

הפקד כולל לא מעט פונקציות מחזור חיים ולכן אני חושב שיהיה מעניין להפוך אותו ל Functional Component ולראות בדרך כמה תבניות של React Hooks.

המשך קריאה

בואו נכתוב משחק זיכרון ב React עם useReducer

18/01/2020

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

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

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

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

const initialState = {
  visibleCards: new Set(),
  currentTurn: new Set()
};

כל לחיצה על קלף מוסיפה אותו ל currentTurn, וכשזה מתמלא אנחנו (אולי) מעבירים את הקלפים משם ל visibleCards ובכל מקרה מאפסים את ה currentTurn. את כל הלוגיקה הזאת אני מעדיף לא לכתוב בתוך קוד הקומפוננטה: אני אוהב שהקומפוננטות שלי כוללות כמה שפחות קוד ומתמקדות רק באיך להציג את המידע על המסך. האלטרנטיבה, כאשר יש לי לוגיקת סטייט מורכבת שקשורה לקומפוננטה בודדת היא הפונקציה useReducer.

פונקציית useReducer מאפשר להגדיר במקום אחר ביישום פונקציה בשם reducer שאחראית על הלוגיקה, ולחבר אותה לקומפוננטה. במקרה שלנו אפשר לכתוב בקובץ אחר לגמרי את פונקציית ה reducer (יחד עם פונקציית עזר קצרה) לתיאור חוקי המשחק:

const reducer = produce((state, { type, payload }) => {
  const { cards } = payload;
  if (state.currentTurn.size === 2) {
    startNewTurn(state, cards);
  }

  if (type === "click") {
    const { idx } = payload;
    if (!state.currentTurn.has(idx) && !state.visibleCards.has(idx)) {
      state.currentTurn.add(payload.idx);
    }
  }
});

function startNewTurn(state, cards) {
  const turnCards = Array.from(state.currentTurn);
  if (turnCards.every(c => cards[c] === cards[turnCards[0]])) {
    state.visibleCards = new Set([...state.visibleCards, ...state.currentTurn]);
  }
  state.currentTurn = new Set();
}

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

function MemoryGame(props) {
  const { cards } = props;
  const [state, dispatch] = useReducer(reducer, initialState);

  function cardClasses(state, idx) {
    let res = "card";
    if (state.visibleCards.has(idx) || state.currentTurn.has(idx)) {
      res += " visible";
    }
    return res;
  }

  return (
    <div className="game">
      <ul>
        {cards.map((val, idx) => (
          <li
            className={cardClasses(state, idx)}
            onClick={() => dispatch({ type: "click", payload: { idx, cards } })}
          >
            {val}
          </li>
        ))}
      </ul>
    </div>
  );
}

מוזמנים לראות (ולשחק) עם התוצאה בקודסנדבוקס הבא, שכולל גם קצת CSS וגם אפקט שמסתיר באופן אוטומטי את הקלפים שתי שניות אחרי שהפכנו אותם:

https://codesandbox.io/s/billowing-river-tbmzu

חדש באתר: קורס ריאקט לייב - לומדים חודשיים עם מרצה ויוצאים עם פרויקט ביד

08/01/2020

הי חברים,

אני לא מבין איך אנשים עדיין לומדים בכיתות. באמת. הסיטואציה הזאת של לשבת בכיתה מול מרצה, להתאמץ כדי להישאר מרוכז (ולאבד את זה כל פעם מחדש) ובדיוק כשאתה מרגיש שמתחיל להבין יש איזה משהו שמתפרץ עם שאלה הכי לא קשורה ושוב הלכת לאיבוד. אף פעם לא היתה לי חווית לימודים טובה בכיתה. כשאני לומד אונליין מול המחשב אני מרוויח בגדול:

אני יכול לראות את השיעור כמה פעמים שאני צריך עד שאני מבין.

אני יכול לדלג על קטעים שלא מעניינים אותי.

אני יכול להתאמן בלי שאף אחד מסתכל.

ואני יכול לשאול שאלות בלי להרגיש שרק אני לא הבנתי.

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

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

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

הקורס הראשון יהיה React ומיועד למתכנתים שכבר יודעים לכתוב קוד Front End, מכירים JavaScript ברמה סבירה אבל מכל מיני סיבות לא הצליחו עדיין להיכנס לשוק העבודה למשרות ה Front End הטובות באמת. הקורס ייפתח באמצע מרץ ויימשך חודשיים.

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

לכל הפרטים על קורס ריאקט הקרוב מוזמנים לקפוץ לדף הנחיתה החדש שבניתי בקישור https://www.tocode.co.il/bundles/react

נתראה בקורס ינון

קוד סטארטר לפיתוח Dashboard ב React

25/12/2019

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

המשך קריאה