קורס React 2020 שיעור תרגול עבודה עם רשימות

הי ינון

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

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

לדעתי קוד פקד קצר זה משהו שהרבה יותר קל לקרוא ולתחזק, כלומר במקרה שלך קוד כזה:

import React, { useState } from 'react';

export default function Tablesort(props){

  const { data } = props;
  const [sortColumn, setSortColumn] = useState(0);
  const [sortOrder, setSortOrder] = useState(1); // 1 for ascending, -1 for descending
  const [tableHeader, tableData] = sortedTableData(data, sortColumn, sortDirection);

  return(
    <div>
      <table>
        <thead>
          <tr>
            {tableHeader.map((item, index) => (<th key={index} onClick={() => setSortColumn(index)}>{item}</th>))}
          </tr>
        </thead>

        <tbody>
          {tableData.map((item, i) => (
            <tr key={i}>
              {item.map((details, j) => (<td key={j}>{details}</td>))}
            </tr>))}
        </tbody>
      </table>
    </div>
  );
}

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

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

תודה על ההסבר, אני בהחלט מבין את הגישה

הי ינון

בהמשך ל custom hooks יצרתי קובץ utils.js

function useBuildTable (data) {

שמחזירה

return {tableHeader, tableData, sortTable};

ואז בפקד

import {useBuildTable} from '../practice-2/utils';

export default function Tablesort(props){
    const { data } = props;
    const table = useBuildTable(data);
    const tableHeader   = table.tableHeader;
    const tableData     = table.tableData;
    const sortTable     = table.sortTable;

ובפקד נשאר רק הרינדור

לייק 1

שלום ינון,
לא הצלחתי למיין את הטבלה בלי השורה הראשונה,

export default function SortAbleTable(props) {

const { dataTable } = props;

const [ newTableSort, setNewTableSort ] = useState([ ...dataTable ]);

const [count,setCount]=useState(0)

console.log(dataTable);

const headers = newTableSort[0];

function sortTable(index) {

    let table = [ ...dataTable ];

    table = table.sort((a, b) => (b[index] > a[index] ? 1 : -1));

    setNewTableSort(table);

    console.log(newTableSort);

    setCount(c=>c+1)

}

return (

    <div>

        <table key={count}>

            <thead>

                <tr >

                    {headers.map((head, index) => (

                        <th  onClick={() => sortTable(index)}>

                            {head}

                        </th>

                    ))}

                </tr>

            </thead>

            <tbody>

                {newTableSort.map(

                    (data, index) => index != 0 && <tr>{data.map((d, index) => <td >{d}</td>)}</tr>

                )}

            </tbody>

        </table>

    </div>

);

}

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

import React, { useState } from 'react';

export default function SortableTable(props){

    const { data } = props;

    const [ columnToSort, setColumnToSort ] = useState(0);

    const dataToShow = sort(data, columnToSort);

    function sort(data, columnToSort){

        const order = data[1][columnToSort] > data[2][columnToSort];

        

    }

    return (

        <>

            <table>

                <thead>

                    {

                        data[0].map((item, index) => (

                            <th onClick={ () => setColumnToSort(index) }>{item}</th>

                        ))

                    }

                </thead>

                <tbody>

                    {

                        dataToShow.map((item, index) => (     

                            <tr key={index}>

                                {

                                    dataToShow[index].map((item2, index2) => (

                                        <td>{item2}</td>

                                    ))

                                }

                            </tr>

                        )

                        )

                    }

                </tbody>

            </table>

        </>

    )

}

הי

נראה כיוון טוב. זאת הפונקציה למיון מערך ב JavaScript:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

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

בשביל מיון הפוך אפשר להוסיף קריאה ל:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse

זה מה שעשיתי אבל זה לא עובד לא יודעת למה
ואיך מדבגים את זה??

import React, { useState } from 'react';

export default function SortableTable(props){

    const { data } = props;

    const headers = data[0];

    data.shift();

    const [ columnToSort, setColumnToSort ] = useState(0);

    const dataToShow = sortTable( data, columnToSort);

    function sortTable(data, columnToSort){

        const order = data[0][columnToSort] > data[1][columnToSort];

        data.sort(function( a, b ){

            const firstValue = a[columnToSort];

            const secondValue = b[columnToSort];

            if ( firstValue < secondValue )

                if( !order ) return 1; else return -1;

            return 0;

        });

        return data;

    }

    return (

        <>

            <table>

                <thead>

                    {

                        headers.map((item, index) => (

                            <th onClick={ () => setColumnToSort(index)  }>{item}</th>

                        ))

                    }

                </thead>

                <tbody>

                    {

                        dataToShow.map((item, index) => (     

                            <tr key={index}>

                                {

                                    item.map((item2, index2) => (

                                        <td>{item2}</td>

                                    ))

                                }

                            </tr>

                        )

                        )

                    }

                </tbody>

            </table>

        </>

    )

}

יש הודעת שגיאה? מה בדיוק לא עובד? מה את רואה?

אין שגיאה
זה משהו מוזר אני לוחצת על הכותרת של אחת העמודות ולא קורה כלום, לוחצת פעם שניה ונעלמות 2 שורות לוחצת פעם שלישית והכל נעלם
מה יכול להיות?

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

בעיה ראשונה- אני רואה את הפקודה:

data.shift()

שהיא מאוד מטרידה. הפקודה משנה משהו ב data (מוחקת תא מהמערך) ואת מריצה אותה כל פעם שמפעילים את פונקציית הרכיב. זכרי שפונקציית הרכיב אמורה להיות פונקציה טהורה ללא Side Effects, ושינוי מידע בזיכרון זה Side Effect.

בעיה שניה באותו סגנון היא הקריאה ל sort ישירות על data. הפקודה sort משנה את המערך - ושוב זהו Side Effect. ריאקט לא מצפה שזה יקרה. הקריאה ל sortTable צריכה קודם כל להעתיק את data הצידה ואז להפעיל sort על העותק, או להשתמש בספריה שעושה את זה בשבילך כמו:
https://lodash.com/docs/4.17.15#sortBy

אחרי שאת מוחקת את כל ה Side Effects יהיה לנו הרבה יותר קל לדבג: בכלי הפיתוח של הדפדפן אחרי התקנת התוסף React DevTools תוכלי להסתכל על הערך של כל משתני הסטייט והפרופס ולעקוב אחרי החישובים כדי לראות שמקבלים את התוצאה שצריך

שיניתי מה שאמרת ועדיין זה עושה אותו דבר
אני מנסה להדפיס בקונסול את הערך של דטה וכבר בתחילת התרגיל הוא מדפיס לי אותו בלי השורה הראשונה
import React, { useState } from ‘react’;

export default function SortableTable(props){

const { data } = props;

console.log("first",data);

const [ columnToSort, setColumnToSort ] = useState(0);

const dataToShow = sortTable( data, columnToSort);

function sortTable(data, columnToSort){

    const d = data;

    d.shift();

    const order = d[0][columnToSort] > d[1][columnToSort];

    d.sort(function( a, b ){

        const firstValue = a[columnToSort];

        const secondValue = b[columnToSort];

        if ( firstValue < secondValue )

            if( !order ) return 1; else return -1;

        return 0;

    });

    return d;

}

return (

    <>

        <table>

            <thead>

                {

                    data[0].map((item, index) => (

                        <th onClick={ () => setColumnToSort(index)  }>{item}</th>

                    ))

                }

            </thead>

            <tbody>

                {

                    dataToShow.map((item, index) => (     

                        <tr key={index}>

                            {

                                item.map((item2, index2) => (

                                    <td>{item2}</td>

                                ))

                            }

                        </tr>

                    )

                    )

                }

            </tbody>

        </table>

    </>

)

}

אני רואה שפקודת ה shift עדיין נשארה בתוך הקומפוננטה

אבל אני לא מבינה מה הבעיה שהיא תהיה?
היא בתוך הפונקציה והיא מופעלת רק בלחיצה על אחת הכותרות ורק על ההעתק של data

היא לא מופעלת על העתק של data אלא על data עצמו. איפה ראית פעולת העתקה?

אני מעתיקה את data לתוך d ועל d מפעילה את shift
image

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

const d = data;

כל פעולה שתעשי על d תשפיע על data ולהיפך.

נסי את זה:

const arr = [10, 20, 30];
const brr = arr;
brr.push(50);

console.log(arr);
console.log(brr);

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

תודה!! ממש לא שמתי לב,
הגעתי לפיתרון מסויים שעובד, אשמח לשמוע איך אפשר לשפר אותו וגם, לגבי שורה 5

    const [ dataToShow, setDataToShow ] = useState([data[1],data[2],data[3],data[4]]);

אני יודעת שהיא לא דינאמית בעליל אבל ממש לא הצלחתי להגיע לשום פיתרון שיתן לי בבת אחת את כל המערך בלי השורה הראשונה, ניסיתי shift וslice אבל זה מביא לי את התא הראשון ולא את שאר המערך… אשמח לפיתרון יותר יעיל

import React, { useState } from 'react';

export default function SortableTable(props){

    const { data } = props;

    const [ dataToShow, setDataToShow ] = useState([data[1],data[2],data[3],data[4]]);

    function sortTable(dataForSort, columnToSort){

        const order = dataForSort[0][columnToSort] > dataForSort[1][columnToSort];

        dataForSort.sort(function( a, b ){

            const firstValue = a[columnToSort];

            const secondValue = b[columnToSort];

            if ( firstValue < secondValue )

                if( !order ) return 1; else return -1;

            if ( firstValue > secondValue )

                if( order ) return 1; else return -1;

            return 0;

        });

        setDataToShow([...dataForSort]);

    }

    return (

        <>

            <table>

                <thead>

                    {

                        data[0].map((item, index) => (

                            <th onClick={() => sortTable(dataToShow, index)}>{item}</th>

                        ))

                    }

                </thead>

                <tbody>

                    {

                        dataToShow.map((item, index) => (    

                            <tr key={index}>

                                {

                                    item.map((item2, index2) => (

                                        <td>{item2}</td>

                                    ))

                                }

                            </tr>

                            

                        )

                        )

                    }

                </tbody>

            </table>

        </>

    )

}

הי,

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

data = [10, 20, 30, 40];
withoutFirst = data.slice(1);
console.log(withoutFirst);

אבל יותר מעניין - למה את צריכה לשמור את dataToShow בתור משתנה State ?

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

אשמח לשמוע איך אתה היית עושה את זה?