Оглавление:

Введение

В этой статье я расскажу обо всех хуках React, их функциональности и вариантах использования. Я постараюсь быть кратким, так что давайте углубимся.

использовать состояние()

Когда вы создаете веб-приложение React, вы часто будете обновлять данные HTML, когда в Javascript происходят определенные события. В ванильном Javascript это обычно выглядит примерно так:

let count = 0

function Increment(){
    count = count + 1
    document.getElementById('someID').innerText = count
}

document.getElementById('button').onClick = Increment

Это работает, но требует обновления элементов из DOM. Это связано с тем, что ванильный Javascript не имеет состояния, а это означает, что Javascript не знает о документе и его элементах. React, однако, имеет полное состояние. Поэтому React будет следить за элементами в документе и соответствующим образом обновлять отображаемый вид.

import React from 'react'


const App = () => {
    let count = 0

    const Increment = () => {
        count = count + 1
        console.log(count)
    }

    return (
        <div>
            <h1>{count}</h1>
            <button onClick={Increment}>
                +
            </button>
        </div>
    )
}

export default App

Учитывая эту информацию, может показаться, что что-то вроде этого должно работать нормально. Однако, как вы можете видеть ниже, это ничего не делает.

Почему это? Что ж, React не отслеживает все элементы, а только те, которые вы укажете. В то время как переменная сама может обновляться, отображаемое представление не обновляется. Здесь на помощь приходит useState(). Должна быть указана любая переменная, которую вы хотите обновить в отображаемом представлении при изменении. Чтобы использовать useState(), вам нужно импортировать его из React, например:

import React, { useState } from 'react'

Отсюда мы можем реализовать переменную с полным состоянием, объявив константу со скобками. Внутри скобок начните с ввода имени переменной; в данном случае «посчитать». Следуйте за этим с именем функции, чтобы установить ее значение. Обычно это делается путем добавления «set» перед тем, что вы назвали своей переменной; в данном случае setCount.

Теперь вы просто назначите свою константу useState(), передав ей значение по умолчанию для вашей переменной. Я решил начать с 0, так как я создаю счетчик, но вы можете передать любое значение, например, строку или объект.

import React, { useState } from 'react'


const App = () => {
    //A Stateful Variable
    const [count, setCount] = useState(0)

    return (
        <div>
            <h1>{count}</h1>
            <button>
                +
            </button>
        </div>
    )
}

export default App

Как только это объявлено, на него можно ссылаться тем же методом в вашем HTML. Однако для повторения подсчета вы больше не можете напрямую настраивать переменную следующим образом:

count = count + 1

Это вернет ошибку, потому что технически count является постоянным значением и не может быть скорректирован. Чтобы изменить переменную с полным состоянием, вы должны использовать функцию, которую мы определили; в данном случае называется setCount. Это будет выглядеть примерно так:

<button onClick={() => { setCount(count + 1) }}>+</button>

Как только это будет реализовано, ваш счетчик должен работать.

Подводя итог, useState() используется для описания переменной с полным состоянием, которая будет обновлять визуализируемую веб-страницу при ее изменении.

использоватьредусер()

Отказ от предыдущего хука: useState(). У нас есть useReducer(). Этот хук используется для объединения нескольких переменных с полным состоянием в один или несколько вызовов функций. По сути делаешь как ее пометил и сокращаешь.

Давайте начнем с приложения React по умолчанию и импортируем useReducer():

import React, { useReducer } from 'react'

const App = () => {
    
    return (
        <div>
            Hello World
        </div>
    )
}

export default App

Аналогично объявлению переменной с полным состоянием, вам нужно объявить константу для нашей переменной-редюсера:

const [state, dispatch] = useReducer(reducer, { count: 0, inverse: 0 })

Однако в редюсере мы указываем состояние и диспетчер. Состояние ссылается на объект, который содержит наши переменные. Dispatch похожа на функцию set в обычной переменной с полным состоянием и будет использоваться для настройки объединенных переменных с полным состоянием позже.

При назначении useReducer() нашей переменной вы заметите 2 различия в передаваемых свойствах. Первым из них является «редуктор», он относится к функции, которую мы объявим позже, которая обрабатывает изменение состояния. Второе отличие заключается в том, что мы передаем объект с двумя переменными: count и inverse. Это просто связанные переменные с полным состоянием.

Наша функция редуктора может быть объявлена ​​вне нашего приложения:

const reducer = (state, action) => { }

Для этого требуется параметр состояние и действие. state относится к связанным переменным и передается, поэтому у вас всегда есть доступ к текущим значениям state. действие используется для переключения между тем, как вы хотите взаимодействовать с этими переменными, например так:

const reducer = (state, action) => {
    switch (action.type) {
        case "IncrementOnly":
            //Only increase the count but dont decrease the inverse
        case "IncrementAndDecrement":
            //Increase the count and Decrease the inverse
        default:
            return state
    }
}

При манипулировании значениями state вам нужно будет вернуть весь измененный объект следующим образом:

const reducer = (state, action) => {
    switch (action.type) {
        case "IncrementOnly":
            return { count: state.count+1, inverse: state.inverse }
        case "IncrementAndDecrement":
            return { count: state.count+1, inverse: state.inverse-1 }
        default:
            return state
    }
}

Как вы можете видеть в приведенном выше коде, когда я «IncrementOnly», я должен установить значение обеих переменных, несмотря на то, что я изменяю только одну. В IncrementAndDecrement значение счетчика увеличивается на единицу, а обратное значение уменьшается на единицу.

Прежде чем использовать эту функцию, давайте быстро создадим пользовательский интерфейс:

<div>
    <span><h1>Count: {state.count}</h1></span>
    <span><h1>Inverse: {state.inverse}</h1></span>

    <button>
        Increment
    </button>
</div>

Затем на нашей кнопке просто добавьте событие onclick и укажите отправку, передав тип как «IncrementAndDecrement»:

<button onClick={() => { dispatch({ type: "IncrementAndDecrement" }) }}>
    Increment
</button>

Теперь вы должны увидеть что-то вроде этого:

Хук useReducer() очень похож на useState(), но при правильном использовании он может уменьшить количество вызовов функций и очистите свою кодовую базу.

использоватьЭффект()

Этот хук немного отличается от того, чего мы касались до сих пор. По сути, это событие, которое вызывается каждый раз перед обновлением отображаемого представления. Для начала давайте импортируем useEffect.

import React, { useEffect } from 'react'

Теперь мы можем создать функцию, которая будет выполняться каждый раз, когда обновляется визуализированный вид:

import React, { useEffect } from 'react'

const App = () => {
    //Use effect function
    useEffect(() => {
        console.log("View updated")
    })

    return (
        <div>Hello World</div>
    )
}

export default App

Теперь каждый раз, когда страница обновляется или элемент с полным состоянием повторно отображается, вы увидите журнал «Просмотр обновленных» в консоли.

Как правило, вы будете использовать useEffect() для извлечения из API или любых других функций, которые вам нужны при загрузке страницы. В этом примере мы будем использовать Axios для извлечения некоторых данных из API прототипирования JsonPlaceholder.

Сначала нам нужно установить библиотеку Axios и импортировать ее в наш скрипт:

npm install axios
import axios from 'axios'

Теперь мы можем ПОЛУЧИТЬ данные заполнителя из ранее упомянутого API:

import React, { useEffect } from 'react'
import axios from 'axios'

const App = () => {
    useEffect(() => {
        axios.get("https://jsonplaceholder.typicode.com/comments")
        .then((res) => {
            
        })

        console.log("View updated")
    })

    return (
        <div>Hello World</div>
    )
}

export default App

Нам нужно импортировать useState(), определить переменную data и присвоить ей некоторые извлеченные данные JSON:

//Add 'useState' to import
import React, { useEffect, useState } from 'react'
import axios from 'axios'

const App = () => {
    //Define 'data' variable
    const [data, setData] = useState("")

    useEffect(() => {
        axios.get("https://jsonplaceholder.typicode.com/comments")
        .then((res) => {
            //Grab the first comment and its email
            //assign it to the 'data' variable
            setData(res.data[0].email)
            console.log("API CALLED")
        })
    })

    return (
        <div>Hello World</div>
    )
}

export default App

Переменная «data» теперь содержит первое электронное письмо из полученного JSON, и мы можем показать его в нашем HTML следующим образом:

<div>
    <h1>{data}</h1>
</div>

Теперь ваша веб-страница должна выглядеть так:

Однако, если вы посмотрите на консоль, вы заметите проблему.

API запрашивается дважды. Это связано с функциональностью useEffect(). Он вызывается каждый раз, когда элемент обновляется, и мы не обязательно хотим, чтобы это происходило. В этом случае это происходит только дважды. Один раз, когда страница загружается, и один раз, когда мы обновляем переменную «данные» с полным состоянием. Представьте себе более крупный проект с несколькими повторными рендерингами, вызываемыми в одном экземпляре веб-страницы. Это может значительно снизить производительность вашего API, не говоря уже о ненужном распределении пропускной способности.

К счастью, есть встроенное решение этой проблемы:

useEffect(() => {
    ...
}, []) //<--- Add an empty array after the function declaration

Просто добавьте пустой массив после объявления функции. Этот массив может содержать любые переменные с полным состоянием, которые вы хотите выполнять, когда они изменяются. В большинстве случаев вам не понадобятся никакие переменные для обновления этой функции, если вы просто добавите их, например:

useEffect(() => {
    ...
}, [data, etc, etc])

использоватьСсылка()

Этот хук, по сути, представляет собой версию React функций document.getElementBy в ванильном Javascript. Это позволяет вам сохранить ссылку на элемент и получить доступ ко всем его свойствам, когда это необходимо.

Начните с этого скрипта, который импортирует useRef() и добавляет базовый HTML. Мы хотим, чтобы этот скрипт принимал значение нашего ввода и обновлял текст элемента заголовка при нажатии кнопки «Изменить имя».

import React, { useRef } from 'react'

const App = () => {
    return (
        <div>
            <h1>Some Name</h1>
            <input type="text" placeholder='Example...'/>
            <button onClick={onClick}>Change Name</button>
        </div>
    )
}

export default App

Далее мы определим нашу ссылочную переменную:

const App = () => {
    //Our Reference Variable
    const inputRef = useRef(null)

    return (
        <div>
            <h1>Seth</h1>
            <input type="text" placeholder='Example...' />
            <button onClick={onClick}>Change Name</button>
        </div>
    )
}

Сначала мы передаем null, потому что на следующем шаге мы будем назначать ссылку.

const App = () => {
    const inputRef = useRef(null)

    const onClick = () => {
        ...
    }

    return (
        <div>
            <h1>Seth</h1>
            <input type="text" placeholder='Example...' ref={inputRef} />
            <button onClick={onClick}>Change Name</button>
        </div>
    )
}

В элемент ввода мы добавляем свойство ref и присваиваем ему нашу ссылочную переменную. Затем создайте функцию onClick и назначьте ее кнопке.

В нашей функции onClick мы просто получим доступ к inputRef.current. Это просто представляет текущее состояние элемента, на который указывает ссылка, и оттуда мы можем получить доступ к любым свойствам, которые может хранить наш элемент. В этом случае нам нужно свойство value.

import React, { useRef } from 'react'

const App = () => {
    const inputRef = useRef(null)

    const onClick = () => {
        console.log(inputRef.current.value)
    }

    return (
        <div>
            <h1>Seth</h1>
            <input type="text" placeholder='Example...' ref={inputRef} />
            <button onClick={onClick}>Change Name</button>
        </div>
    )
}

export default App

Теперь давайте добавим функцию изменения имени, импортировав useState(), настроив переменную name и установив ее значение равным текущему значению ссылки.

import React, { useRef, useState } from 'react'

const App = () => {
    const inputRef = useRef(null)
    const [name, setName] = useState("Name")

    const onClick = () => {
        setName(inputRef.current.value)
    }

    return (
        <div>
            <h1>{name}</h1>
            <input type="text" placeholder='Example...' ref={inputRef} />
            <button onClick={onClick}>Change Name</button>
        </div>
    )
}

export default App

Теперь у нас есть работающий пример useRef(). По сути, это версия React-запросов DOM в ванильном Javascript, но она, безусловно, может пригодиться.

использоватьмакетэффект()

Этот хук, по-видимому, идентичен ранее упомянутому хуку useEffect(). Единственная реальная разница в том, когда она вызывается. Вы видите, что useEffect() вызывается сразу после того, как страница изначально отображает свои элементы. Принимая во внимание, что useLayoutEffect() вызывается до того, как страница первоначально отобразит свои элементы. Вы можете увидеть это в следующем примере:

import React, { useLayoutEffect, useEffect, useRef } from 'react'

const App = () => {
    //Reference To Input
    const inputRef = useRef(null)
    
    //Effect Setting Value to Name
    useEffect(() => {
        inputRef.current.value = "Name"
    }, [])
    //Layout Effect Logging the Input Value: should be 'Dave'
    useLayoutEffect(() => {
        console.log(inputRef.current.value)
    }, [])

    return (
        <div>
            <input type="text" value='Dave' ref={inputRef} />
        </div>
    )
}

export default App

Когда страница обновляется, первым зарегистрированным значением является значение по умолчанию: «Дэйв». И это несмотря на то, что в хуке useEffect() мы установили значение «имя». Так зачем вам это нужно? Он просто предотвращает отображение страницы значений по умолчанию на мгновение, например, при загрузке из API. Он просто дает альтернативу хуку useEffect().

использовать императивхэндл()

Теперь мы рассмотрим некоторые хуки более высокого уровня, и этот не исключение. useImperativeHandle() позволяет вызывать изменение состояния повторно используемого компонента из его родителя. Если это не совсем понятно, рассмотрим следующий пример:

У нас есть наше основное приложение, затем у нас есть повторно используемый компонент; в данном случае называется «Кнопка».

Приложение:

import React from 'react'
import Button from './Button'

function App() {
    return (
        <div>
            <button>Button From Parent</button>
            <Button />
        </div>
    )
}

export default App

Кнопка:

import React, { useState } from 'react'

const Button = (props) => {
    const [toggle, setToggle] = useState(false)

    return (
        <>
            <button onClick={() => {
                setToggle(!toggle)
            }}>
                Button From Child
            </button>
            
            {toggle && <span>Toggle</span>}
        </>
    )
}

export default Button

Вот как в настоящее время работают эти два скрипта:

«Кнопка от ребенка» включает и выключает диапазон, но мы хотим, чтобы «Кнопка от родителя» делала это. Лучший способ приблизиться к повторно используемому компоненту — использовать хук Imperative Handle.

Для реализации этого мы будем использовать комбинацию Imperative Handle и Reference hook. Мы можем начать с импорта useRef() в приложение, а также forwardRef и useImperativeHandle() в Button.

Приложение:

import React, { useRef } from 'react'

Кнопка:

import React, { forwardRef, useImperativeHandle, useState } from 'react'

Теперь в Button мы начинаем с использования forwardRef, помещая его вокруг функции Button и добавляя параметр ref следующим образом:

const Button = forwardRef((props, ref) => {
    ...
})

Это позволяет нам использовать хук useImperativeHandle(). Теперь мы можем объявить хук, передав ему ref и функцию, возвращающую объект. Внутри которого мы определим новую функцию Toggle.

const Button = forwardRef((props, ref) => {
    const [toggle, setToggle] = useState(false)
    
    useImperativeHandle(ref, () => ({
        Toggle() {
            setToggle(!toggle)
        }
    }))

    return (
        <>
            <button>
                Button From Child
            </button>
            
            {toggle && <span>Toggle</span>}
        </>
    )
})

Как только это настроено, мы можем перейти к приложению и реализовать ссылку на кнопку.

function App() {
    const buttonRef = useRef(null)

    return (
        <div>
            <button>Button From Parent</button>
            <Button ref={buttonRef}/>
        </div>
    )
}

Наконец, все, что нам нужно сделать, это добавить прослушиватель onClick к нашей родительской кнопке и указать его на функцию Toggle этой кнопки.

Приложение:

import React, { useRef } from 'react'
import Button from './Button'

function App() {
    const buttonRef = useRef(null)

    return (
        <div>
            <button onClick={() => {buttonRef.current.Toggle()}}>
                Button From Parent
            </button>

            <Button ref={buttonRef}/>
        </div>
    )
}

export default App

Кнопка:

import React, { forwardRef, useImperativeHandle, useState } from 'react'

const Button = forwardRef((props, ref) => {
    const [toggle, setToggle] = useState(false)

    useImperativeHandle(ref, () => ({
        Toggle() {
            setToggle(!toggle)
        }
    }))

    return (
        <>
            <button>
                Button From Child
            </button>
            
            {toggle && <span>Toggle</span>}
        </>
    )
})

export default Button

Если вы когда-нибудь будете создавать повторно используемый компонент, подобный этому, вы можете рассмотреть возможность реализации useImperativeHandle() и forwardRef(). крючки. Это, вероятно, избавит вас от повторения спагетти-кода и избавит вас от головной боли при масштабировании вашего приложения.

использоватьконтекст()

Контекст — это способ управления состоянием вашего приложения. Вместо того, чтобы реализовывать переменные с полным состоянием в компоненте высшего порядка и передавать их через свойства дочерним компонентам. Вы можете создать контекст приложения, который позволяет совместно использовать переменные с дочерними компонентами. Позволь мне привести пример.

Представьте, что вы создаете социальное приложение и хотите, чтобы пользователь мог вводить статус в своем профиле. Вместо того, чтобы получать этот статус из API каждый раз, когда вы меняете состояния, вы можете поделиться им через контекст приложения.

Мы начнем с нашего базового приложения и двух компонентов. Компонент состояния и компонент обновления.

Приложение:

import React, { useState} from 'react'
import Status from './Status'
import Update from './Update'

const App = () => {
    const [status, setStatus] = useState("")

    return (
        <div>
            <Update />
            <Status />
        </div>
    )
}

export default App

Положение дел:

import React from 'react'

const Status = () => {
    
    return (
        <div>
            <h2>Status:</h2>
        </div>
    )
}

export default Status

Обновлять:

import React from 'react'

const Update = () => {
    
    return (
        <div>
            <input type="text" placeholder="What's Your Status?" />
            <button>Submit</button>
        </div>
    )
}

export default Update

Теперь мы можем начать с создания контекста, его экспорта и обертывания всех компонентов, к которым мы хотим иметь доступ, с помощью AppContext.Provider. Затем мы присваиваем значение всем переменным и функциям, которые хотим передать компонентам.

Приложение:

import React, { useState, createContext } from 'react'
import Status from './Status'
import Update from './Update'

//Create App Context
export const AppContext = createContext(null)

const App = () => {
    const [status, setStatus] = useState("")
    
    return (
        //Wrap components
        <AppContext.Provider value={{ status, setStatus }}>
            <Update />
            <Status />
        </AppContext.Provider>
    )
}

export default App

Поскольку мы экспортировали AppContext, мы можем импортировать его и useContext() в наши компоненты.

import React, { useContext } from 'react'
import { AppContext } from './App'

Теперь в наших компонентах можно получить доступ к переданным переменным и функциям, например так:

Положение дел:

import React, { useContext } from 'react'
import { AppContext } from './App'
 
const Status = () => {
    
    const {status} = useContext(AppContext)

    return (
        <div>
            <h2>Status: {status}</h2>
        </div>
    )
}

export default Status

Обновлять:

import React, { useContext, useRef } from 'react'
import { AppContext } from './App'

const Update = () => {
    
    const {setStatus} = useContext(AppContext)
    const inputRef = useRef(null)
    
    return (
        <div>
            <input type="text" placeholder="What's Your Status?" ref={inputRef} />
            <button onClick={() => {setStatus(inputRef.current.value)}}>Submit</button>
        </div>
    )
}

export default Update

В конечном счете, для небольших проектов это может показаться излишним. Однако, как только вы начнете масштабироваться, вы начнете видеть потенциал для организации.

использоватьMemo()

Этот хук позволяет системе кэшировать результат функции и повторно выполнять функцию только в случае обновления определенных элементов. Вообще говоря, это полезно только для расчетов/алгоритмов на стороне клиента.

Начнем с примера. У нас есть приложение, которое ПОЛУЧАЕТ список комментариев, находит самый длинный комментарий и отображает его на экране. Для этого примера у нас также есть кнопка, которая переключает видимость ‹span›, вызывая изменение состояния. Код выглядит следующим образом:

import React, { useState, useEffect } from 'react'
import axios from 'axios'

const App = () => {
    const [data, setData] = useState(null)
    const [toggle, setToggle] = useState(false)

    //GET comments from JsonPlaceholder
    useEffect(() => {
        axios.get("https://jsonplaceholder.typicode.com/comments")
        .then((res) => {
            setData(res.data)
        })
    }, [])

    //This functionion iterates through all the comments finding the longest one
    const FindLongestComment = (comments) => {
        if(!comments) return null

        let longestComment = ""
        for (let i = 0; i < comments.length; i++) {
            let currentComment = comments[i].body
            if(currentComment.length > longestComment.length)
            {
                longestComment = currentComment
            }
            
        }

        console.log('Computed Longest Comment.')
        return longestComment
    }

    return (
        //Display the longest comment found
        <div>
            <p>{FindLongestComment(data)}</p>

            <button onClick={() => { setToggle(!toggle) }}>Toggle</button>

            {toggle && <span>Toggled On</span>}
        </div>
    )
}

export default App

Проблема в том, что всякий раз, когда представление перерисовывается, оно снова вызывает эту функцию, как вы можете видеть:

Решением для такого сценария является использование хука useMemo(). Это позволит системе кэшировать уже обработанную функцию до тех пор, пока не изменятся данные, которые она обрабатывает. Сначала нам нужно импортировать useMemo().

import React, { ... useMemo } from 'react'

const App = () => { ... }

Затем нам нужно объявить новую переменную, которая будет использоваться вместо нашей функции. Мы назовем это getLongestName. Хук useMemo() требует двух параметров. Первая — это некоторая функция, которая возвращает значение. Второй — массив зависимостей. Это относится к массиву переменных для прослушивания изменений. В нашем случае мы хотим прослушивать переменную data на наличие изменений и повторно выполнять нашу функцию только тогда, когда это происходит.

const FindLongestComment = (comments) => { ... }

//                                 Function Returning Value,   Dependency Array
const getLongestComment = useMemo(() => FindLongestComment(data), [data])

Осталось только заменить FindLongestComment() в нашем HTML на getLongestComment. Теперь это наш готовый код:

import React, { useState, useEffect, useMemo } from 'react'
import axios from 'axios'

const App = () => {
    const [data, setData] = useState(null)
    const [toggle, setToggle] = useState(false)

    //GET comments from JsonPlaceholder
    useEffect(() => {
        axios.get("https://jsonplaceholder.typicode.com/comments")
        .then((res) => {
            setData(res.data)
        })
    }, [])

    //This functionion iterates through all the comments finding the longest one
    const FindLongestComment = (comments) => {
        if(!comments) return null

        let longestComment = ""
        for (let i = 0; i < comments.length; i++) {
            let currentComment = comments[i].body
            if(currentComment.length > longestComment.length)
            {
                longestComment = currentComment
            }
            
        }

        console.log('Computed Longest Comment.')
        return longestComment
    }

    const getLongestComment = useMemo(() => FindLongestComment(data), [data])

    return (
        //Display the longest comment found
        <div>
            <p>{getLongestComment}</p>

            <button onClick={() => { setToggle(!toggle) }}>Toggle</button>

            {toggle && <span>Toggled On</span>}
        </div>
    )
}

export default App

Вы заметите, что в консоли, независимо от того, обновляется ли представление, мы не выполняем функцию снова. Его следует выполнять только в случае обновления страницы или изменения данных. В большинстве случаев этот хук не требуется, поскольку большую часть времени такого рода функции будут выполняться на сервере. Тем не менее, есть крайние случаи для чего угодно, и именно этого ожидала команда React.

использоватьCallback()

Хотя этот хук используется в очень похожих обстоятельствах с useMemo(), он кэширует саму функцию, а не возвращаемое значение функции. Обычно вы используете это при передаче функциональности дочерним компонентам. Это связано с тем, что каждый раз, когда вы изменяете состояние, функция, на которую ссылаются, создается заново. Если вы хотите поместить ссылку на функцию в массив зависимостей для примера, она все равно будет вызываться каждый раз при изменении состояния.

Представьте, что у вас есть приложение и дочерний компонент:

Приложение:

import React, { useState, useEffect, useMemo } from 'react'
import Child from './Child'

const App = () => {
    const [data, setData] = useState("Hello")
    const [toggle, setToggle] = useState(false)

    const getData = () => {
        return data
    }

    return (
        <div>
            <Child getData={getData} />

            <button onClick={() => { setToggle(!toggle) }}>
                Toggle
            </button>

            {toggle && <span>Toggled On</span>}
        </div>
    )
}

export default App

Ребенок:

import React, { useEffect } from 'react'

function Child({ getData }) {
    useEffect(() => {
        console.log("Getting Data...")
    }, [getData])


    return <div>{getData()}</div>
}

export default Child

В настоящее время они работают так:

Данные извлекаются каждый раз, когда представление отображается, несмотря на то, что его следует вызывать только один раз. Решением этой проблемы является передача функциональности через хук useCallback(). Мы можем реализовать это, просто обернув функцию с помощью useCallback() и определив массив зависимостей.

Приложение:

const getData = useCallback(() => {
    return data
}, [data])

Без каких-либо изменений программа теперь должна работать правильно:

Данные извлекаются только при загрузке страницы и остаются неизменными, несмотря на изменение состояния переключателя.

Это специфический хук для использования, но он был сделан по уважительной причине, и однажды он может вам пригодиться. Держите эти крючки в своем поясе с инструментами и создавайте потрясающие приложения React!

Кредит:

Я написал эту статью на основе замечательного руководства, предоставленного PedroTech на YouTube; Вы можете найти видео Здесь. Спасибо всем за чтение, я надеюсь, что это было так же полезно для чтения, как и для меня, чтобы написать.