Установщик useState () в реактивных крючках не работает

#reactjs #react-hooks

#reactjs #реагирующие крючки

Вопрос:

У меня вызван пользовательский крючок useAddFriend , вот код:

 import { useCallback, useState } from 'react'
import { Users }from '../data/userDummy'

const useAddFriend = () => {
    const [roomId, setRoomId] = useState("default")

    const findUser = useCallback((username) => {
        for(let user of Users) {
            if(username === user.username) {
                setRoomId("newRoomId")
            }
        }
    }, [])

    return { roomId, findUser }
}

export default useAddFriend;
  

Проблема в том, setRoomId что никогда не обновляйте roomId. Я уже убедился, что он удовлетворил if condition вышеуказанному. Но он всегда возвращается default .

Вот как я использую крючок для компонента React:

 const AddFriend = () => {
    const [username, setUsername] = React.useState('')
    const { roomId, findUser } = useAddFriend()
    const history = useHistory()

    const handleInputChange = (event) => {
        setUsername(event.target.value)
    }
    
    const handleAddFriend = () => {
        findUser(username)
        setUsername("")
        history.push(`/${roomId}`)
    }

    ...
}
  

Ответ №1:

Я думаю, причина здесь:

 const handleInputChange = (event) => {
    setUsername(event.target.value)
}

const handleAddFriend = () => {
    findUser(username)
    setUsername("")
    history.push(`/${roomId}`) // <= This line may execute before the roomId is fully set
}
  

Чтобы убедиться, что вы получите правильное roomId значение после выполнения крючка, рекомендуется использовать вместе с useEffect

 const handleAddFriend = () => {
    findUser(username)
    setUsername("")
}

useEffect(()=> { if(roomId!=='default') history.push(`/${roomId}`) }, [roomId]);
  

Комментарии:

1. Спасибо!! Никогда не думал, что эта проблема была вызвана history . Не могли бы вы сказать мне, почему или дать мне какую-нибудь ссылку. Заранее спасибо

2. Выполняется ли перехват асинхронно?

3. @AlifRamdani useState (то же самое с setState в class-component) является асинхронным. И они, как правило, выполняют несколько обновлений за один раз. Поэтому не совсем надежно, если мы рассматриваем их как синхронные и рекомендуем использовать useEffect, как я только что упомянул

4. Ах, я забыл, что setState является асинхронным. Спасибо

Ответ №2:

Вам нужно удалить useCallback или передать аргумент, который вы хотите обновить, в квадратных скобках

 const findUser = useCallback((username) => {
    for(let user of Users) {
        if(username === user.username) {
            setRoomId("newRoomId")
        }
    }
}, [roomId])
  

Комментарии:

1. Привет @Max, не могли бы вы добавить сюда несколько ссылок или еще несколько пояснений?

2. reactjs.org/docs/hooks-reference.html#usecallback

3. можете ли вы удалить history.push?

4. @Max Я пробовал, и это все еще не работает. И я также уверен, что это не имеет никакого отношения к проблеме