ToCode
1.43K subscribers
3.42K links
טיפים קצרים למתכנתים מאת ינון פרק
Download Telegram
</div>

<div className="carousel-indicators">
{images.map((_, index) => (
<button
key={index}
className={\carousel-indicator ${index === currentIndex ? 'active' : ''}\}
onClick={() => goToSlide(index)}
aria-label={\Go to slide ${index + 1}\}
/>
))}
</div>

{images.length > 1 && (
<div className="carousel-countdown">
Next image in: {countdown}s
</div>
)}
</div>
)
}

export default ImageCarousel


גם הוא עובד הפעם עם משתנה סטייט יחיד.

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

import { useState, useEffect } from 'react'
import './ImageCarousel.css'

interface CountdownTimerProps {
interval: number
onTimeout: () => void
}

const CountdownTimer: React.FC<CountdownTimerProps> = ({ interval, onTimeout }) => {
const [countdown, setCountdown] = useState(interval / 1000)

useEffect(() => {
const timer = setInterval(() => {
setCountdown((prevCountdown) => {
if (prevCountdown <= 1) {
onTimeout()
return interval / 1000 // Reset countdown
}
return prevCountdown - 1
})
}, 1000) // Update every second

return () => clearInterval(timer)
}, [interval, onTimeout])

return (
<div className="carousel-countdown">
Next image in: {countdown}s
</div>
)
}

interface ImageCarouselProps {
images: string[]
interval?: number
}

const ImageCarousel: React.FC<ImageCarouselProps> = ({ images, interval = 3000 }) => {
const [currentIndex, setCurrentIndex] = useState(0)

const goToSlide = (index: number) => {
setCurrentIndex(index)
}

const goToPrevious = () => {
setCurrentIndex((prevIndex) =>
prevIndex === 0 ? images.length - 1 : prevIndex - 1
)
}

const goToNext = () => {
setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length)
}

if (images.length === 0) {
return <div className="carousel-empty">No images to display</div>
}

return (
<div className="carousel-container">
<div className="carousel-wrapper">
<button
className="carousel-btn carousel-btn-prev"
onClick={goToPrevious}
aria-label="Previous image"
>
&#8249;
</button>

<div className="carousel-image-container">
<img
src={images[currentIndex]}
alt={\Slide ${currentIndex + 1}\}
className="carousel-image"
/>
</div>

<button
className="carousel-btn carousel-btn-next"
onClick={goToNext}
aria-label="Next image"
>
&#8250;
</button>
</div>

<div className="carousel-indicators">
{images.map((_, index) => (
<button
key={index}
className={\carousel-indicator ${index === currentIndex ? 'active' : ''}\}
onClick={() => goToSlide(index)}
aria-label={\Go to slide ${index + 1}\}
/>
))}
</div>

{images.length > 1 && (
<CountdownTimer
key={currentIndex}
interval={interval}
onTimeout={goToNext}
/>
)}
</div>
)
}

export default ImageCarousel


כאן שוב יש לנו את ה set בתוך set, אבל הפעם הזזתי את האפקט רק לקומפוננטה של השעון שהיא הרבה יותר קטנה וכל משתנה סטייט שמור בקומפוננטה שלו.

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

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

ולפעמים אנחנו לומדים משהו בגלל שהוא חשוב.

כשכולם היו צריכים ללמוד כל שבוע JavaScript Framework חדש היו אנשים שעצרו כדי ללמוד איך בנוי דפדפן, איך JavaScript עובדת ואיך לבנות JavaScript Framework מאפס. מה האתגרים בפיתוח Single Page Application ואיך פותרים אותם בלי Framework, איך לכתוב פיתרון Router מאפס. לא היה לידע הזה ערך מיידי. זה לא הופיע בשום רשימת דרישות במודעות דרושים ולא הופיע באף סילבוס. ובכל זאת אנשים שהשקיעו את העבודה בלימוד היסודות הצליחו ללמוד פריימוורקים חדשים הרבה יותר מהר ולעבוד נכון יותר.

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

כשמתחילים ללמוד משהו חדש כדאי להבין למה אני לומד את זה, איך יראה תהליך הלמידה ואיך תשתנה המוטיבציה שלי לאורך התהליך. כשאני יוצא לדרך עם הבנה של המסלול הסיכוי להצלחה גדל משמעותית.
🔥1
האם handoff היא אבסטרקציה דולפת?
ספריות סוכנים עדכניות מוסיפות את המושג של handoff כדי להעביר שליטה מסוכן אחד לסוכן אחר. הנה קטע דוגמה מתוך openai agents sdk:

from agents import Agent

billing_agent = Agent(name="Billing agent")
refund_agent = Agent(name="Refund agent")


triage_agent = Agent(name="Triage agent", handoffs=[billing_agent, refund_agent])


וזאת מתוך ה SDK של מיסטרל:

finance_agent = client.beta.agents.update(
agent_id=finance_agent.id,
handoffs=[ecb_interest_rate_agent.id, web_search_agent.id]
)

* Allow the ecb_interest_rate_agent to handoff the conversation to the graph_agent or calculator_agent *
ecb_interest_rate_agent = client.beta.agents.update(
agent_id=ecb_interest_rate_agent.id,
handoffs=[graph_agent.id, calculator_agent.id]
)

* Allow the web_search_agent to handoff the conversation to the graph_agent or calculator_agent *
web_search_agent = client.beta.agents.update(
agent_id=web_search_agent.id,
handoffs=[graph_agent.id, calculator_agent.id]
)


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

מבחינת מימוש handoff הוא בסך הכל Tool Call שגורם ל Runner לבקש השלמה מסוכן אחר ומעביר את המשך לולאת הטיפול לאותו סוכן אחר. אז באיזה מובן זו אבסטרקציה דולפת?

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

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

2. אם נקרא את רשימת ההודעות ב Session ונרצה להמשיך להשתמש בה נצטרך לשים לב שכל Handoff הוא בעצם הודעת Tool Call וחייבים להעביר את התשובה שלו ל AI (כי בהודעות Tool Call ה AI מצפה לראות תשובה של כל Tool Call בהיסטוריית השיחה).

3. שם הכלי הדיפולטי של handoff ב agents sdk הוא transfer_to_<agent_name>. זה אולי לא משהו שנבחר בטעות לעתים קרובות אבל בטוח צריכים להיות מודעים לזה שיש כלי כזה שנשלח למודל כשאנחנו מסתכלים על היסטוריית שיחה ומנסים להבין מה קרה. הרבה פעמים נצטרך תיאור יותר יצירתי לכלי ה handoff.

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

5. מה קורה כשה Tool Call מסתיים? החזרת השליטה דורשת עצירה ידנית של לולאת הפעלת הכלים ואז הפעלה של כלי handoff שוב לסוכן אחר, או החזרת ערך מכלי ה handoff עצמו.

עם כל הרצון לקבל ספריות סוכנים "אפויות" עם כמה שיותר יכולות ואבסטרקציות, את הסיפור של handoff יהיה יותר חכם לממש לבד בקוד האפליקציה שלכם. כמו שדברים בנויים היום אבסטרקציה זו לא מאפשרת להתקדם בלי להכיר את המימוש עליו היא בנויה.
👍1
כמה הרגלי אבטחה שיכולים לעזור לקופיילוט בענן
כלי פיתוח מבוססי AI יכולים לעשות הרבה נזק ולכן כשאנחנו מפעילים אותם בענן אנחנו יכולים קצת לצמצם את הסיכון - בענן יש לנו שליטה טובה יותר במכונת הפיתוח ואנחנו יכולים להחליט מה הסוכן יוכל או לא יוכל לעשות. הנה כמה דברים שכדאי לשים לב כשאתם נעזרים בקופיילוט בענן:

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

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

3. עדיף לא לתת ל AI להוסיף חבילות למערכת. גם יותר טוב מבחינת חומת האש שלא יתקין שום דבר וגם אף פעם אנחנו לא יודעים אם הוא לא מתקין משהו זדוני בטעות. בהנחיות הכלליות של קופיילוט בענן בקובץ .github/copilot-instructions.md אני אכתוב משהו כמו:

Do not install additional packages from npm. Implement all required functionality with the existing packages or using vanilla JavaScript.


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

5. קשה לקרוא Session Log של AI ולאחרונה גיטהאב עשו את זה יותר קשה והוסיפו עוד שתי לחיצות כדי להגיע לפלט המלא. ועדיין הפלט הזה יכול לחשוף שני סוגים של מידע חשוב - הראשון הוא כשהמודל עושה שטויות ושובר דברים והשני כשהמודל לא מבין עקרונות בסיסיים באיך המערכת בנויה ולכן הקוד שהוא כותב עלול להפר הנחות יסוד ולסכן את המערכת.

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

רק בגלל שמצאת פיתרון בסטאק אוברפלו שפותר כמעט את הבעיה שלך לא אומר שהפיתרון הזה יפתור את הבעיה שלך. או שהוא אפילו קרוב.

ורק בגלל ש AI הצליח לכתוב קוד שעושה כמעט מה שאת צריכה לא אומר שהוא יוכל לכתוב בדיוק את הקוד שאת צריכה.

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

https://research.kudelskisecurity.com/2025/08/19/how-we-exploited-coderabbit-from-a-simple-pr-to-rce-and-write-access-on-1m-repositories/

בקצרה קודרביט העלו סביבת Code Review בענן. מהסביבה הזאת הם הגדירו גישה לכל הנכסים הפרטיים שלהם כולל לבסיס הנתונים ומפתחות פרטיים. בנוסף לתוך הסביבה הזאת הם טענו את הקוד של המשתמשים להם היה צריך לעשות Code Review ונתנו ל AI לרוץ בתוך כל המרק הזה כדי לקרוא את קוד המשתמשים ולהבין אותו. וכאילו שזה לא מספיק מזעזע עד לפה הם גם איפשרו למשתמשים להגדיר כלי בדיקה משלהם וכך גרמו לכשל "הרצת קוד מרחוק" על אותה סביבת בדיקות - כלומר משתמש זדוני יכל לטעון כל סקריפט ולהריץ אותו בתוך הסביבה הפרטית של קודרביט ולהגיע לכל המידע של החברה.

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

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

https://github.com/settings/apps/authorizations

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

https://tidewave.ai/

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

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

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

1. במקום להתחיל פיצ'ר מקובץ HTML אני מתחיל את השיחה מהדפדפן כשאני מסתכל על אלמנט ספציפי ואף מסמן אותו בממשק של טיידוייב.

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

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

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

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

נ.ב. עוד רעיון יצירתי שלא חקרתי מספיק הוא jazz.app שמציעים ממשק AI של לוח ציור חכם. העתיד הולך להיות מעניין.
מיקרו אופטימיזציות
שימו לב לפעולת ||= בקוד של טובי כאן:

    $token_map ||= {
# semantic foreground styles
# '{text}' => "\e[39m",
'{text}' => "\e[39m",
'{dim_text}' => "\e[90m",
'{h1}' => "\e[1;33m",
'{h2}' => "\e[1;36m",
'{highlight}' => "\e[1;33m",
# resets/util
'{reset}' => "\e[0m", '{reset_bg}' => "\e[49m",
# screen/cursor
'{clear_screen}' => "\e[2J", '{clear_line}' => "\e[2K", '{home}' => "\e[H",
'{hide_cursor}' => "\e[?25l", '{show_cursor}' => "\e[?25h",
# Selection background: faint
'{start_selected}' => "\e[6m",
'{end_selected}' => "\e[0m"
}


זה מגיע מפרויקט צד בשם try:

https://github.com/tobi/try/blob/main/try.rb

אני די בטוח שהוא לא השווה סטטיסטיקות של זמני ריצה או ניסה לטפל בתלונה ממשתמשים. ההבדל בין השמה רגילה ל ||= הוא שולי בהקשר הזה.

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

בשביל המשחק מחקתי את ההגדרה של token_map וביקשתי מ AI להשלים אותה. ג'יפיטי5 השלים עם האופטימיזציה, ג'מיני וקלוד בלי.

האם יום אחד כל כלי ה AI ישתמשו באופטימיזציה זו כברירת מחדל? לדעתי לא, וזה לא משנה. ה AI שם בשביל לעזור. הבנת החשיבות של מתי דברים נוצרים ושמירה לא לעשות עבודה מיותרת תמיד תישאר העבודה שלנו.
1
איפה הסוכן רץ ותהליך העבודה העתידי
סוכן AI שרץ בדפדפן מאפשר לאנשים פחות טכניים להשתתף בתהליך הפיתוח. לאבבל או בייס44 מראים לנו איך זה עובד עם פרויקטים חדשים ו tidewave מראה לנו איך זה עובד על פרויקט ריילס או פיניקס קיים. בשני המקרים העבודה מתוך הדפדפן, הצבעה על אזורים ספציפיים בעמוד ותחילת העבודה מתוך ה"תוצר" מובילים לשיחה על פיצ'רים, איפיונים והתנהגות.

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

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

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

> teach me React from scratch write 10 exercises to try react out for complete beginners

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

פרומפט שני:

> create a solution for each in a tutorial style blog post. Explain all the basic concepts and theory as we advance from basic to more complex

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

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

> expand each blog post to include full beginner friendly explanation

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

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

import { useEffect, useState } from "react";

function Users() {
const [users, setUsers] = useState([]);

useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => setUsers(data));
}, []); // run only once

return (
<ul>
{users.map((u) => (
<li key={u.id}>{u.name}</li>
))}
</ul>
);
}


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

הפיתרון (והחלק הקשה) בלימוד בעזרת AI הוא לקחת כל דוגמה, להדביק אותה לשיחה חדשה ולהתחיל לנהל עליה שיחה עם פרומפטים כמו - "הסבר כל שורה", "איך זה יעבוד במערכת אמיתית?", "האם יש דרך יותר טובה או מודרנית להשיג את אותה מטרה?".
👍1