Skip to content

Tag 18: JavaScript, Custom Hooks

devToJu edited this page Mar 27, 2023 · 3 revisions

Template Strings

Um innerhalb von JSX {"Ich bin ein String in JSX"} Strings zu verketten, kann auf Template Strings zurückgegriffen werden. Anstatt Strings und Variablen durch ein "+" zu verbinden, kann der String in Backticks (`) geschrieben werden. An der Stelle, an der auf die Variable verwiesen wird, wird mit '${variablenName}' auf diese zugegriffen. template-Strings

Weiterführende Infos:

Spreading

Spreading ist eine Funktionalität, welche es ermöglicht die Eigenschaften eines Objektes, schnell und einfach an ein anderes Objekt zu übertragen. Hierzu werden vor dem Objektname drei Punkte geschrieben:

...variablenName

Spreading bei Listen

Vereinfacht das übertragen aller Elemente einer Quell-Liste an eine neue Ziel-Liste.

const quelle = [1, 2, 3]
const ziel = [...quelle]

Zusätzlich können neue Elemente - durch ein Komma separiert - hinzugefügt werden:

const quelle = [1, 2, 3]
const ziel = [...quelle, 4, 5]

Bsp.: Eine Namens-Liste wird kopiert und um einen weiteren Namen erweitert Spreading-Listen

Spreading bei Objekten

Vereinfacht das Übertragen von Attribut-Werten eines Quell-Objekts an ein Ziel-Objekt.

const quelle: {attributA: "Wert A", attributB: "Wert B"}
const ziel: Person = {...quelle}

Anders als bei Listen kann kein neues Attribut hinzugefügt werden. Werden vorhandene Attribute - durch ein Komma separiert - verwendet, wird der Attribut-Wert geändert.

const quelle: Person = {attributA: "Wert A", attributB: "Wert B"}
const ziel: Person = {...quelle, attributB: "Neuer Wert"}

Bsp.: Eine Person wird kopiert und das Attribut Job wird geändert spreading-Objekte

Zugriff auf Objektattribute

Es kann auf zwei Arten auf die Eigenschaften eines Objektes zugegriffen werden. Die Punktnotation 'objektName.AttributName' oder durch ein Names-Literal objektName["AttributName"].

Bsp.: Zugriff auf dasselbe Attribut durch verschiedene Möglichkeiten attributzugriff

Custom Hooks

React Hooks bieten die Möglichkeit, State und andere React-Funktionen in Functional Components zu nutzen, was bisher nur in Class Components möglich war. Wir können eigene Hooks erstellen. Sie stellen eine tolle Möglichkeit dar, Logik wiederverwendbar zu machen. Best Practive ist, dass die Custom Hooks ebenso wie die Standard Hooks mit dem Keyword "use" beginnen.

Bsp Todo:

Unsere App.tsx ist sehr lang. Wir können einen Teil des Codes auslagern, da die Funktionen nichts konkretes mit der App.tsx zutun haben. Wir erstellen unseren Custom Hook.

Wir erstellen also eine ts (tsx ist auch in Ordnung) Datei und lagern den Code dort aus. Wir erstellen eine neue Funktion in der Datei, nennen die Datei in dem Fall useTodos.ts, als auch die Funktion useTodos() und müssen den return anpassen, in dem wir ein Objekt erstellen und alle Werte da reintun, die wir brauchen :

export default function useTodos() {

    const [todos, setTodos] = useState<Todo[]>([])

    useEffect(() => {
        loadAllTodos()
    }, [])

    function loadAllTodos() {
        axios.get("/api/todo")
            .then((getAllTodosResponse) => {setTodos(getAllTodosResponse.data)})
            .catch((error) => {console.error(error)})
    }

    function addTodo(newTodo: NewTodo) {
        axios.post("/api/todo", newTodo)
            .then((addTodoResponse) => {
                //            [] wir erstellen eine neue Liste
                //              ... (spreading) wir nehmen alle Elemente der alten Liste und fügen sie in die neue ein
                //                       , und wir fügen das neue Todo zusätzlich hinzu
                setTodos([...todos, addTodoResponse.data])
            })
            .catch(console.error)
    }

    function updateTodo(todo: Todo) {
        axios.put(`/api/todo/${todo.id}`, todo)
            .then((putTodoResponse) => {
                //Wir wollen das alte Todo ersetzen, alle anderen sollen gleich bleiben
                setTodos(todos.map(currentTodo => {
                    //wir prüfen ob das aktuelle element, das todo ist das wir ersetzten wollen?
                    if (currentTodo.id === todo.id) {
                        //Ja es ist das wir ersetzten wollen: wir returnen das todo aus der response
                        return putTodoResponse.data
                    }
                    else {
                        //Nein es ist ein anderes, wir lassen das so wie es ist
                        return currentTodo
                    }
                }))
            })
            .catch(console.error)
    }

    function deleteTodo(id: string) {
        axios.delete('/api/todo/' + id)
            .then(() => {
                setTodos(todos.filter((todo) => todo.id !== id))
            })
            .catch(console.error)
    }

    return {todos, addTodo, updateTodo, deleteTodo}
}

Jetzt müssen wir die App.Tsx anpassen, damit wir den Custom Hook auch benutzen können und die Funktion aufrufen können. Wir benutzen dafür den Namen der Funktion und speichern dieses in eine Variable und bauen das Objekt in seine einzelnen Eigenschaften aus ( nennt man Destructuring), sodass wir direkt auf die einzelnen Bestandteile des Objekts zugreifen können statt "Objekt.Eigenschaft".

function App() {

    const {todos, addTodo, deleteTodo, updateTodo} = useTodos()

    return (
        <div className="App">
            <Header/>
            <TodoGallery todos={todos} updateTodo={updateTodo} deleteTodo={deleteTodo}/>
            <AddTodo addTodo={addTodo}/>
        </div>
    );
}

Für mehr über Destructuring:

https://www.geeksforgeeks.org/destructuring-of-props-in-reactjs/ oder https://www.w3schools.com/react/react_es6_destructuring.asp

Lösung Musteraufgabe Todo

https://github.com/Flooooooooooorian/hh-23-1-todo

Clone this wiki locally