זהו נושא דיון מלווה לערך המקורי שב־https://www.tocode.co.il/bundles/react/lessons/b5892b02-c3b5-4eb8-badd-9e6629ee91d7
זהו נושא דיון מלווה לערך המקורי שב־https://www.tocode.co.il/bundles/react/lessons/b5892b02-c3b5-4eb8-badd-9e6629ee91d7
שלום,
יש לי כמה שאלות אם אפשר:
1.) לא הבנתי מדוע הפקד SelectCountry צריך לקבל את selectedCountry ולאתחל את ה-value של ה-select באותו ערך, מה המשמעות של זה? הרי כשמשנים את הבחירה השינוי הזה נעשה אוטומטי.
אותו דבר לגבי הפקד - SelectCity.
מצרפת את הקוד עם 2 השורות מסומנות:
const SelectCountry = (props) => {
const { selectedCountry, setSelectedCountry, countries } = props;
return (
//בשורה הבאה:
<select value={selectedCountry} onChange={(e) => setSelectedCountry(e.target.value)}>
<option disabled selected value>Please select a country</option>
{countries.map((country, index) => (
<option key={index} value={country}>{country}</option>
))}
</select>
);
};
const SelectCity = (props) => {
const { selectedCity, setSelectedCity, cities } = props;
return (
//בשורה הבאה:
<select value={selectedCity} onChange={(e) => setSelectedCity(e.target.value)}>
<option disabled selected value>Please select a city</option>
{cities.map((city, index) => (
<option key={index} value={city}>{city}</option>
))}
</select>
);
};
2.) דבר דומה היה בתרגיל של בחירת יום בשבוע, מדוע צריך ב - checkbox לאתחל את ה-checked:
checked={selectedItems.has(item)}
import React from 'react';
import ReactDOM from 'react-dom';
import { useState } from 'react';
function SelectableList(props) {
const { items } = props;
const [selectedItems, setSelectedItems] = useState(new Set());
function toggleItem(add, item) {
if (add) {
selectedItems.add(item);
} else {
selectedItems.delete(item);
}
console.log(selectedItems);
setSelectedItems(new Set(selectedItems));
}
return (
<>
<p>Selected Items: {Array.from(selectedItems).join(', ')}</p>
<ul>
{items.map(item => (
<li key={item} style={{ direction: "rtl" }}>
<label>
{item}
<input
type="checkbox"
checked={selectedItems.has(item)}
onChange={(e) => toggleItem(e.target.checked, item)}
/>
</label>
</li>
))}
</ul>
</>
);
}
const App = () => {
const days = ['Sunday', 'Monday', 'Tuesday','Wednesday', 'Thursday', 'Friday', 'Saturday'];
return (
<div>
<SelectableList items={days}/>
</div>
)
};
// main.js
const root = document.querySelector('main');
ReactDOM.render(<App />, root);
3.) שאלה כללית על ה- useState, אמרת באחד השיעורים שהפונקציה הזו מקבלת פונקצית עדכון או ערך יחיד, ובפונקצית העדכון משתמשים כאשר הערך החדש תלוי בישן. לא הבנתי מדוע צריך את הפונקציה הזו אם אפשר להשתמש במשתנה שהגיע מה-state לדוגמא בקוד הבא:
export default function Counter(props) {
const [count, setCount] = useState(0);
const [delta, setDelta] = useState(1);
function inc() {
setCount(oldValue => oldValue + delta);
}
return (
);
}
למה יש צורך בפונקציה אם אפשר לעשות כך:
function inc() {
setCount(count + delta);
}
תודה רבה!!!
הי
בואי ננסה להתחיל מהסוף - לגבי ה state. מה תהיה התוצאה של הרצת שתי השורות הבאות ברצף?
setValue(val + 1);
setValue(val + 1);
התשובה שהערך בסטייט יעלה ב-1 (ולא ב-2), כי הפעולה של setValue לא משפיעה על המשתנה val והערך שכבר נמצא בתוכו.
לעומת זאת בפונקציות אין לנו בעיה כזאת והקוד הבא:
setValue(v => v + 1);
setValue(v => v + 1);
מעלה את הערך בסטייט ב-2 לפני שנגיע ל render הבא. זה קוד יותר מסודר שממחיש טוב יותר מה הכוונה (אפילו שגם הגירסה הראשונה עובדת בחלק מהמקרים)
…
לגבי הטפסים וקומפוננטת ה Select:
בכל קומפוננטת טופס בריאקט אנחנו יכולים לבחור אם להעביר את המאפיינים value ו onChange או לוותר עליהם. כשמעבירים אותם הקומפוננטה נקראת “קומפוננטה מנוהלת” וריאקט דואג לסנכרן בין הערכים של המשתנים לשני הכיוונים, כלומר כשהערך משתנה בקומפוננטה גם ערכי המשתנים יעודכנו. במקרה שלנו המשתנה הוא selectedCountry והערך שלו יהיה מסונכרן עם מה שיש בקומפוננטה.
אפשרות שניה היא לא להעביר את value ואת onChange. במצב כזה עדיין תיבת ה select תעבוד אבל לא יהיה סינכרון של המידע בחזרה למשתנים שלנו ולכן יהיה קשה יותר להשתמש במידע “איזה ארץ ועיר נבחרו” במקומות אחרים בתוכנית.
מקווה שעזרתי ואם דברים עדיין לא ברורים מוזמנת לרשום שאלות המשך
1.) בקשר ל-state.
באופציה השניה:
setValue(v => v + 1);
setValue(v => v + 1);
מאיפה לוקח ריאקט את הפרמטר ‘v’? ממה ששמור כרגע בסטייט? ז"א הערך בסטייט מתעדכן לאחר ביצוע כל שורה?
אם כן מה הכוונה מה שאמרת שהעדכונים מתבצעים בצורה אסינכרונית? אם הפונקציות מתחילות להתבצע במקביל אז שתיהן מקבלות את אותו ערך מהסטייט.
2.) לגבי קומפוננטת ה-select התכוונתי לאפשרות שלישית שהיא לטפל רק באירוע של onChange ולא לתת ערך ב-checked, ז"א רק להוריד מהתוכנית את השורה הזו:
checked={selectedItems.has(item)}
אני מבינה שכאשר נותנים ערך ב-value או ב-checked חייבים גם לטפל באירוע onChange אבל לא הבנתי למה גם להיפך, ניסיתי רק להוריד את השורה ההיא והכל עובד מצוין.
היי ינון
איך אפשר לקבל את ה-index (ולא את ה-value) מתיבת select box?
אפשר להשתמש במאפיין selectedIndex
של אירוע שינוי בתיבת select. הנה דוגמת קוד:
היי ינון
כתבתי את אותו הקוד שאתה כתבת והוא עובד כמו שצריך אבל הוא זורק לי את כמה שגיאות :
1 . Warning: Each child in a list should have a unique “key” prop.
2 . Use the defaultValue
or value
props on instead of setting selected
on .
3 . Warning: value
prop on select
should not be null. Consider using an empty string to clear the component or undefined
for uncontrolled
4 . Unchecked runtime.lastError: The message port closed before a response was received.
זה הקוד
import { useState } from "react";
function SelectCountry(props){
const {countries,country,replaceCountry} = props;
return(
<>
<select value={country} onChange={(e)=>replaceCountry(e.target.value)}>
<option disabled selected value>Select Country</option>
{countries.map((item,index)=>(
<option value={item}>{item}</option>
))}
</select>
</>
);
}
function SelectCity(props){
const {cities,city,setCity} = props;
return(
<>
<select value={city} onChange={(e)=>setCity(e.target.value)}>
<option disabled selected value>Select City</option>
{cities.map((item,index)=>(
<option value={item}>{item}</option>
))}
</select>
</>
);
}
function SelectCountryAndCity(props){
const {countriesAndCities} = props;
const [country,setCountry] = useState(null);
const [city,setCity] = useState(null);
const countries = Object.keys(countriesAndCities);
const cities = countriesAndCities[country];
const replaceCountry=(newCountry)=>{
setCountry(newCountry);
setCity(null);
}
return(
<div>
<p>You Live {country} / {city}</p>
<SelectCountry
countries={countries}
country={country}
replaceCountry={replaceCountry}
/>
{cities && <SelectCity
cities={cities}
city={city}
setCity={setCity}
/>}
</div>
);
}
export default SelectCountryAndCity
הי אייל
תודה על תשומת הלב. אכן בריאקט מומלץ לא להשתמש ב null בתור ערך של select ועדיף להשתמש במחרוזת ריקה. זאת התוכנית המתוקנת:
import { useState } from 'react'
function SelectCountry(props) {
const { countries, country = "", replaceCountry } = props;
return (
<>
<select value={country} onChange={(e) => replaceCountry(e.target.value)} >
<option disabled value>
Select Country
</option>
{countries.map((item, index) => (
<option value={item}>{item}</option>
))}
</select>
</>
);
}
function SelectCity(props) {
const { cities, city = "", setCity } = props;
return (
<>
<select value={city} onChange={(e) => setCity(e.target.value)} >
<option disabled value={undefined}>
Select City
</option>
{cities.map((item, index) => (
<option value={item}>{item}</option>
))}
</select>
</>
);
}
function SelectCountryAndCity(props) {
const { countriesAndCities } = props;
const [country, setCountry] = useState("");
const [city, setCity] = useState("");
const countries = Object.keys(countriesAndCities);
const cities = countriesAndCities[country];
const replaceCountry = (newCountry) => {
setCountry(newCountry);
setCity("");
};
return (
<div>
<p>
You Live {country} / {city}
</p>
<SelectCountry
countries={countries}
country={country}
replaceCountry={replaceCountry}
/>
{cities && <SelectCity cities={cities} city={city} setCity={setCity} />}
</div>
);
}
לגבי ההערה -
1 . Warning: Each child in a list should have a unique “key” prop.
היא מאוד חשובה ואני משאיר אותה כאן בכוונה. יש עליה שיעור בהמשך הקורס:
https://www.tocode.co.il/bundles/react/lessons/key?tab=video