ynonp
29 ביולי, 2021, 8:30pm
#40
הי
משהו לא נכון בשימוש שלך באופרטור סימן-שאלה-נקודותיים. אופרטור זה נועד להחזיר ערך ולא לביצוע פעולה. בנוסף אין משמעות לשינוי המשתנה score עצמו. צריך לחשוב עליו בתור “מצביע” למקום בזיכרון בו ריאקט שומר את הערך האמיתי.
הכתיב הנכון יהיה:
function updateScore(inx2) {
const diff = square[inx2] ? 10 : -5;
setScore(currentScore => currentScore + diff);
}
shlomi
29 ביולי, 2021, 9:26pm
#41
תודה רבה,
אך כשאני משנה לכתיב שכתבת למעלה מתקבלת השגיאה: Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
אני לא מצליחה להבין את הבעיה
ynonp
30 ביולי, 2021, 10:26am
#42
אה כן אני רואה. הבעיה בגדול שאת מפעילה את הפונקציה updateScore במקום להעביר אותה פנימה לתוך הקומפוננטה Sq. כלומר הבעיה בשורות:
<Sq func = {updateScore(0)} isRed = {square[0]}/>
<Sq func = {updateScore(1)} isRed = {square[1]}/>
<Sq func = {updateScore(2)} isRed = {square[2]}/>
<Sq func = {updateScore(3)} isRed = {square[3]}/>
<Sq func = {updateScore(4)} isRed = {square[4]}/>
בשביל להבין את ההבדל בין העברה להפעלה אני ממליץ לצפות בשיעור הזה:
https://www.tocode.co.il/bundles/frontend/lessons/js-functions
ואז לענות על התרגיל השני כאן:
https://www.tocode.co.il/bundles/frontend/lessons/functions-lab
תדביקי כאן את הפיתרון לתרגיל השני (או אם את נתקעת ספרי ונתקדם יחד לאט עם זה), ואחרי שתפתרי אותו תראי אם את יכולה להשתמש באותו טריק כדי לתקן גם את הבאג בקוד שלך
shlomi
2 באוגוסט, 2021, 11:07am
#43
הפיתרון לתרגיל השני:
<script>
var b1 = document.querySelector('#btn1');
var b2 = document.querySelector('#btn2');
var panel = document.querySelector('p');
function writeText(text) {
panel.textContent=text;
}
b1.addEventListener('click', ()=>writeText('Yo'));
b2.addEventListener('click', ()=>writeText('Nice To Meet You'));
</script>
הפיתרון לפונקציה updateScore:
<Sq func = {()=>updateScore(0)} isRed = {square[0]}/>
<Sq func = {()=>updateScore(1)} isRed = {square[1]}/>
<Sq func = {()=>updateScore(2)} isRed = {square[2]}/>
<Sq func = {()=>updateScore(3)} isRed = {square[3]}/>
<Sq func = {()=>updateScore(4)} isRed = {square[4]}/>
זה עובד!
תודה רבה
לייק 1
shlomi
2 באוגוסט, 2021, 12:17pm
#44
זה הקוד המלא
אשמח אם תוכל לתת לי טיפים לייעול הקוד
export default function Sq(props){
const {isRed,func} = props;
const backgroundColor = isRed ? 'red' : 'gray';
let style={
width:"100px",
height:"100px",
backgroundColor: backgroundColor,
margin:"10px",
display:"inline-block"
}
return(
<>
<div style = {style} onClick = {func}></div>
</>
)
}
export default function Boxes(props){
const {square,func} = props;
return(
<>
{
square.map((element,index) => <Sq isRed = {element} func={()=>(func(index))}></Sq>)
}
</>
)
}
export default function Score(props){
const {newGame,score} = props;
return(
<>
<div>
<button onClick={newGame}>new game</button>
<p>{score}</p>
</div>
</>
)
}
const App = () => {
const [square,setSquare] = useState([false,false,false,false,false,false,false,false,false,true])
const [score,setScore] = useState(0);
function newGame(inx){
setInterval(
function(){
let newArr = [false,false,false,false,false,false,false,false,false,false];
newArr[Math.floor(Math.random() * 5)] = true;
setSquare(newArr);
},1000
)
setScore(0);
}
function updateScore(inx2) {
const diff = square[inx2] ? 10 : -5;
setScore(currentScore => currentScore + diff);
}
return (
<div>
<Boxes square = {square} func = {updateScore}/>
<Score score = {score} newGame ={newGame}/>
</div>
)
}
ynonp
4 באוגוסט, 2021, 11:50am
#45
הי
הבעיה המרכזית כאן שנשארה זה המערך ב State. אין בו באמת צורך; מספיק לשמור את האינדקס של המקום היחיד שהוא true
yeshaya
28 באוגוסט, 2021, 1:41am
#47
היי פיתרון שלי לתרגיל 1, אשמח להערות. חילקתי ל3 קבצים
yeshaya
28 באוגוסט, 2021, 10:07pm
#48
שמתי לב שאמרת לרשום קוד ולא תמונות רק עכשיו
מצרף את הקוד שלי לפתרון תרגיל 2 , אשמח להערות
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import List from './list.js';
import Input from './input.js';
const App = () => {
const [arrUesrInput, setArrUserInput] = useState("");
const arrColors = ['red', 'blue','purple','yellow','pink'];
let updateList = (word) => {setArrUserInput(word);};
return (
<>
<Input updateList={updateList}/>
<List arrUesrInput={arrUesrInput}
arrColors={arrColors}/>
</>
)
};
// main.js
const root = document.querySelector('main');
ReactDOM.render(<App />, root);
================================================
import React, { useState } from 'react';
export default function Input(props) {
const {updateList} = props;
return (
<div>
<input placeholder='choose color' onChange={(e) => {updateList(e.target.value)}}></input>
</div>
)
}
=============================================
import React, { useState } from 'react';
export default function List(props) {
const { arrUesrInput, arrColors } = props;
/* Inputs of the user*/
// const arrUserInputs = list.split(' ');
return (
<>
<div style={{ display: 'flex' }}> please choose from the following colors:
{arrColors.map((color, index) =>
(<div key={index} style={{ marginLeft: '10px', color: 'blue' }}>{color}</div>))} </div>
<ul>
{
arrColors.map(function foo(color, index) {
if ((arrUesrInput.split(' ')).includes(color)) {
return (<li key={index} value={color}>{color}</li>);
}
})
}
</ul>
</>
)
}
ynonp
30 באוגוסט, 2021, 6:21am
#49
הי,
לגבי תרגיל 1 - נראה טוב. יש לי כמה דברים מוזרים עם random. קודם כל:
const random = r => Math.floor(Math.random() * 10)
אבל הפונקציה לא משתמשת ב r בכלל. היה עדיף לכתוב את זה בלעדיו:
const random = () => Math.floor(Math.random() * 10);
דבר שני זה בתוך הקוד השורה:
const [box, setBox] = useState(random);
שאני חושב שהתכוונת לכתוב עם סוגריים של הפעלה אחרי random כלומר:
const [box, setBox] = useState(random());
לגבי הקוד עצמו שמתי לב שאתה מעביר את הפונקציות changeBoxColor ו updateScore מקומפוננטה App לקומפוננטה Box, אבל הרבה פעמים קורא לשתי הפונקציות האלה יחד אחת אחרי השניה. נדמה לי שעדיף לחשוב על מבנה פונקציות שלא תצטרך לקרוא להן יחד - לדוגמה פונקציית winRound ו loseRound, כאשר אחת גם תעלה נקודות וגם תשנה צבע והשניה רק תוריד נקודות.
וראיתי גם הרבה מאפייני style בקוד. שווה להסתכל על הספריות emotion.js:
ו Styled Components:
https://www.tocode.co.il/past_workshops/52
שנותנות דרך טובה יותר לכתוב קוד סטייל בתוך קוד JS. או אולי הכי פשוט להשתמש ב CSS.
הי, איך הקוד של תרגיל 2?
import React from 'react';
import ReactDOM from 'react-dom';
import { useState } from 'react';
import '../css/main.css';
const List = (props) => {
const { filter } = props;
const listOfItem = ['michael', 'ron', 'yoni', 'yarin','ido',
'aviad', 'ynon', 'moshe', 'david', 'yaron'];
return (
<>
<ul>
{listOfItem.map((item, index) => (
item.includes(filter) && <li>{item}</li>
))}
</ul>
</>
)
}
const SrarchBox = (props) => {
const { newSearch } = props;
return(
<>
<input type="text" onChange={newSearch} />
</>
)
}
const App = () => {
const [filter, setFilter] = useState([]);
const newSearch = (e) => setFilter(e.target.value);
return (
<>
<SrarchBox newSearch={newSearch}/>
<List filter={filter} />
</>
)
};
// main.js
const root = document.querySelector('main');
ReactDOM.render(<App />, root);
ynonp
3 באוקטובר, 2022, 7:00pm
#51
שים לב שכשאתה כותב שדה קלט עם onChange:
<input type="text" onChange={newSearch} />
תמיד להוסיף לו גם value, אחרת עלולים להיות באגים מוזרים שהטקסט בתיבה לא מתואם עם המשתנה
הי, בתרגיל משחק ניחוש מספר, רציתי להסתיר את הכפתור של הגרלת המספר לאחר הלחיצה, ולהראות את השדה לניחוש המספרים לשם כך כתבתי קוד כזה:
function hideShow() {
if (givenNumber !== undefined) {
givenNumberContainer.classList.add("hide");
comparedNumberContainer.classList.remove("hide");
}
else {
comparedNumberContainer.classList.add("hide");
givenNumberContainer.classList.remove("hide");
}
}
hideShow()
כשאני מרעננת את העמוד אני מקבלת הודעת שגיאה:
Uncaught TypeError: Cannot read properties of null (reading ‘classList’)
איך אני משנה את המצב הזה?
תודה!
ynonp
26 ביוני, 2023, 1:55pm
#53
הי,
בעבודה עם ריאקט אנחנו לא מוסיפים או מורידים קלאסים עם classList, אלא רק מתוך פונקציית הקומפוננטה בתוך ה JSX. כלומר משהו כזה:
function Game() {
const [givenNumber, setGivenNumber] = useState(undefined);
if (givenNumber) {
return <div>hide button</div>
else {
return <div>show button</div>
}
}
shimki
1 באוגוסט, 2023, 8:35am
#54
שלום ינון,
בתרגיל מספר 3:
אני צריך לשמור בסטייט 4 פרטים: userName, password, country, city.
אפשר ליצור סטייט לכל אחד בנפרד.
אבל אני רוצה לשמור הכל בתוך אובייקט משהו בסגנון הזה:
const [userInformation, setUserInformation] = useState([{userName: ‘’, password: ‘’, country: ‘’, city: ‘’}]);
אבל אני מקבל שגיאה שריאקט לא עובדת עם אובייקטים,
וכאן לשאלה:
האם זה באמת כך, ומה הדרך הכי טובה לשמור את זה,
האם ליצור לכל פרט סטייט? אני מחפש דרך יותר נקייה.
עוד שאלה:
לפתרון שאלה זו, יש לי שני input שמפעילים onChange עם שמעביר את ה value.
אני יכול לעשות פונקציה שונה לכל אחד שתשמור בסטייט את הערך, אבל אני רוצה לעשות פונקציה אחת שתדע לבדוק מי ה input ששלח ולפי זה לדעת באיזה סטייט לשמור.
הדרך שחשבתי לפתור את זה, זה לעשות:
const arr = [[0, "user name:", "fux972"], [1, 'password:', 'SH@fux10']];
{arr.map( el => (
<div key={el}>
<label>
choose your {el[1]}
<input type="text" placeholder={el[2]} onChange={ (e) => changeuserNameOrPassword(e.target.value, el[0])}/>
</label>
</div>
))}
האם זה הדרך הנכונה?
ynonp
1 באוגוסט, 2023, 1:19pm
#55
הי
אין בעיה לשמור אוביקט בסטייט אבל באמת זה פחות מומלץ כי בהמשך יהיה לך יותר קשה לעשות Refactor לדברים.
עדיף מאוד בתור Best Practice לפצל לכמה משתני סטייט.
אם בכל זאת אתה מחליט לשמור אוביקט אחד צריך לשים לב לנושא Mutability ולהעביר אוביקט חדש כל פעם לפונקציית ה setter. אני מדבר על זה בשיעור כאן:
https://www.tocode.co.il/bundles/react/lessons/state?tab=video
לשאלה השניה אני הייתי מעדיף לראות סטייט וקוד יותר פשוטים, כלומר בסטייט לשמור שני משתני מחרוזת רגילים (שם משתמש וסיסמה) וב JSX לכתוב שתי תיבות input אחת אחרי השניה ולא בלולאה. הסיבה:
המבנה של הטופס מגיע מהעיצוב. סיכוי טוב שיהיו עוד התאמות והבדלים בין שני ה input-ים גם אם לא בגירסה הראשונה אז לאורך זמן. לדוגמה סיסמה בטח תקבל type=password, אולי יהיו וולידציות מסוימות ושונות שתרצה לשים על כל שדה בטופס הזה. החיבור בין שם משתמש לסיסמה כאן נראה משהו מאוד זמני שבקרוב יישבר.
כן אפשר לדמיין מערכת גנרית יותר של טפסים שמקבלת ״פרטים של טופס״ ויוצרת קומפוננטות מתאימות ל input-ים. למשל ספריה כמו:
useForm
שווה להסתכל עליה ולראות אם אתה מצליח לשלב/לעבוד איתה בתור בונוס.
shimki
1 באוגוסט, 2023, 5:42pm
#56
תודה רבה,
לא חשבתי על זה שיהיה בהמשך הבדלים ביניהם,
צריך תמיד מצד אחד לנסות לקצר קוד כמה שאפשר, ומצד שני שיהיה קריא ופונקציונלי,
מכאן נבעו השאלות שלי.
המשך ערב טוב!
digital
16 בנובמבר, 2023, 10:15am
#57
אני אשמח לדעתך על הקוד שכתבתי לתרגיל 3
function Page1(props) {
const { setUserName, setPassword } = props;
return (
<div>
<p>הזן שם משתמש וסיסמא</p>
<input type="text" onChange={(e) => setUserName(e.target.value)} /><span>שם משתמש</span>
<br />
<input type="password" onChange={(e) => setPassword(e.target.value)} /><span>סיסמא</span>
</div>
);
}
function Page2(props) {
const { setCity, setCountry } = props;
return (
<div>
<p>הזן אזור מגורים</p>
<input type="text" onChange={(e) => setCountry(e.target.value)} /><span>ארץ </span>
<br />
<input type="text" onChange={(e) => setCity(e.target.value)} /><span>עיר</span>
</div>
);
}
function Page3(props) {
const { userName, password, country, city } = props;
return (
<div>
<p>הפרטים שהזנת:</p>
<p>שם משתמש {userName}</p>
<p>סיסמא {password}</p>
<p>ארץ {country}</p>
<p>עיר {city}</p>
</div>
)
}
export default function FormPages() {
const [counter, setCouter] = useState(0);
const [userName, setUserName] = useState("");
const [password, setPassword] = useState("");
const [city, setCity] = useState("")
const [country, setCountry] = useState("");
function next() {
setCouter(x => x + 1);
}
function prev() {
setCouter(x => x - 1);
}
switch (counter) {
case 0:
return (
<>
<Page1 setPassword={setPassword} setUserName={setUserName} />
<button type="button" onClick={next}>הבא</button>
</>);
break;
case 1:
return (
<>
<Page2 setCountry={setCountry} setCity={setCity} />
<button type="button" onClick={next}>הבא</button>
<button type="button" onClick={prev}>הקודם</button>
</>)
break;
case 2:
return (
<>
<Page3 userName={userName} password={password} country={country} city={city} />
<button type="button" onClick={prev}>הקודם</button>
</>);
break;
}
}```
ynonp
18 בנובמבר, 2023, 5:06pm
#58
הי,
זה נראה טוב מבחינת הסטייט, העברה של פונקציות העדכון לילדים והיחס בין כל הקומפוננטות.
כיוון אחד שהייתי מנסה לשפר הוא לשמור את כל קומפוננטות העמודים במערך, משהו כזה:
const pages = [Page1, Page2, Page3]
במקום ה switch/case שיש לך שם, כי אז יהיה יותר קל להוסיף עוד דפים אם נצטרך
מצרפת קוד של תרגיל 3.
אשמח מאד לדעת האם יש דרך יותר יעילה ונכונה לפתור אותו
Details:
import React, { useState } from "react";
import User from "./User";
import Country from "./Country";
import Summary from "./Summary";
const Details = () => {
const [userName, setUserName] = useState("");
const [password, setPassWord] = useState("");
const [country, setCountry] = useState("");
const [city, setCity] = useState("");
const [page, setPage] = useState(1)
return (
<>
{page == 1 ? <User setPage={setPage} setUserName={setUserName} setPassWord={setPassWord}></User>
: page == 2 ? <Country setPage={setPage} setCountry = {setCountry} setCity = {setCity}></Country>
: <Summary setPage={setPage} user = {userName} pass = {password} cou = {country} city = {city}></Summary>}
</>
)
}
export default Details
User:
import React, { useState } from "react";
const User = (props) => {
const {setPassWord, setUserName, setPage} = props
return (
<>
<input onChange={e => setUserName(e.target.value)} type="text" placeholder="Type user name"></input>
<input onChange={e => setPassWord(e.target.value)} type="text" placeholder="Type Password"></input>
<button disabled>Previous</button>
<button onClick={e => setPage(2)}>Next</button>
</>
)
}
export default User
Country:
import React, { useState } from "react";
const Country = (props) => {
const {setPage, setCity, setCountry} = props
return (
<>
<input onChange={e => setCountry(e.target.value)} type="text" placeholder="Type your country"></input>
<input onChange={e => setCity(e.target.value)} type="text" placeholder="Type your city"></input>
<button onClick={e => setPage(1)}>Previous</button>
<button onClick={e => setPage(3)}>Next</button>
</>
)
}
export default Country
Summary:
import React, { useState } from "react";
const Summary = (props) => {
const {user, pass, cou, city, setPage} = props
return (
<>
<p>Your user name is {user}</p>
<p>Your password is {pass}</p>
<p>You live in {city}, {cou}</p>
<button onClick={e => setPage(2)}>Previous</button>
<button disabled>Next</button>
</>
)
}
export default Summary
ynonp
19 בנובמבר, 2024, 1:30pm
#60
הי נראה מעולה דבר אחד שהייתי כותב אחרת זה בקובץ הראשון אני לא אוהב להשתמש בסימן שאלה ונקודותיים במקרים כאלה כי קצת קשה לקרוא את זה, ומעדיף כתיב של switch כלומר:
import React, { useState } from "react";
import User from "./User";
import Country from "./Country";
import Summary from "./Summary";
const Details = () => {
const [userName, setUserName] = useState("");
const [password, setPassWord] = useState("");
const [country, setCountry] = useState("");
const [city, setCity] = useState("");
const [page, setPage] = useState(1);
const renderPage = () => {
switch (page) {
case 1:
return <User setPage={setPage} setUserName={setUserName} setPassWord={setPassWord} />;
case 2:
return <Country setPage={setPage} setCountry={setCountry} setCity={setCity} />;
case 3:
return <Summary setPage={setPage} user={userName} pass={password} cou={country} city={city} />;
default:
return null;
}
};
return <>{renderPage()}</>;
};
export default Details;
לפעמים גם נוח לשים את כל ה props באוביקט אחד ולהעביר אותם לילדים עם סימן שלוש נקודות:
import React, { useState } from "react";
import User from "./User";
import Country from "./Country";
import Summary from "./Summary";
const Details = () => {
const [userName, setUserName] = useState("");
const [password, setPassWord] = useState("");
const [country, setCountry] = useState("");
const [city, setCity] = useState("");
const [page, setPage] = useState(1);
// Collect all props into a single object
const sharedProps = {
setPage,
userName,
setUserName,
password,
setPassWord,
country,
setCountry,
city,
setCity,
};
const renderPage = () => {
switch (page) {
case 1:
return <User {...sharedProps} />;
case 2:
return <Country {...sharedProps} />;
case 3:
return <Summary {...sharedProps} />;
default:
return null;
}
};
return <>{renderPage()}</>;
};
export default Details;