Я пытаюсь получить данные из Spotify API. Поскольку для этого мне нужен токен доступа, я создал собственный хук для анализа токена из URL-адреса, который приходит с сервера. У меня также есть еще один пользовательский хук с фактическим запросом к API, который принимает проанализированный токен в качестве аргумента. Оба собираются в родительский крючок.
Я не могу заставить это работать, так как токен никогда не достигает области действия хука запроса, поэтому он терпит неудачу. Если я разбираю токен и делаю запрос в том же хуке, все работает нормально. Я намеревался сделать хук для каждого запроса, так как это не один, поэтому я хотел передать токен в качестве аргумента.
Пользовательский хук токена
export default () => {
const [ token, setToken ] = useState('')
useEffect(() => {
const { access_token } = queryString.parse(window.location.search)
return setToken(access_token)
}, [])
return token
}
Запрос крюка
export default function useFetchUserData(token) {
//state
const initialUserState = {
display_name: '',
external_url: '',
images: ''
}
const [ userData, setUserData ] = useState(initialUserState)
const [ isLoading, setIsLoading ] = useState(false)
const [ isError, setIsError ] = useState(false)
useEffect(() => {
async function getUserData() {
setIsLoading(true);
setIsError(false);
const spotify = axios.create({
baseURL: 'https://api.spotify.com/v1/me',
headers: {
'Authorization': `Bearer ${token}`
}
})
try {
const userRes = await spotify('/')
.then( res => { return res.data });
setUserData({
display_name: userRes.display_name,
external_url: userRes.external_urls.spotify,
images: userRes.images[0].url
})
} catch (error) {
setIsError(true)
}
setIsLoading(false);
}
getUserData();
}, [])
const data = {
userData,
isLoading,
isError
}
return data
}
Родительский крючок
export default function Home() {
const token = useParseToken()
const { userData, isLoading, isError } = useFetchUserData(token);
if (isLoading) return <BarLoader />;
if (isError) return <div>Oops! something went wrong</div>;
return (
<Fragment>
<Header userData = {userData}/>
</Fragment>
)
}
Из вашего примера кода const { token } = useTokenParser() может быть неправильно, должно быть const token = useTokenParser()
Затем внутри useFetchUserData вы должны правильно обработать случай, когда token === "", потому что первый вызов всегда получает этот случай.
Большое спасибо @hackape, это сработало. Я слишком увлекся деструктурированием.
спасибо @Jared, возможно, пришло время попробовать!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы должны использовать createContext API реакции. Сохраните токен как контекст. и используйте его где угодно. Я думаю, этот репозиторий вам поможет.
В вашем случае происходит то, что вы устанавливаете состояние в хуке useEffect в своем пользовательском хуке, чтобы установить токен. Однако вы возвращаете токен из этого хука, не дожидаясь запуска эффекта, поэтому при первом вызове вашего useFetchUserData хука он получит пустую строку в качестве токена. Чтобы решить эту проблему, вы должны реализовать хук useFetchUserData для запуска после того, как токен станет доступен или изменится.
export default function useFetchUserData(token) {
//state
const initialUserState = {
display_name: '',
external_url: '',
images: ''
}
const [ userData, setUserData ] = useState(initialUserState)
const [ isLoading, setIsLoading ] = useState(false)
const [ isError, setIsError ] = useState(false)
useEffect(() => {
async function getUserData() {
setIsLoading(true);
setIsError(false);
const spotify = axios.create({
baseURL: 'https://api.spotify.com/v1/me',
headers: {
'Authorization': `Bearer ${token}`
}
})
try {
const userRes = await spotify('/')
.then( res => { return res.data });
setUserData({
display_name: userRes.display_name,
external_url: userRes.external_urls.spotify,
images: userRes.images[0].url
})
} catch (error) {
setIsError(true)
}
setIsLoading(false);
}
if (token !== '' || token !== null) {
getUserData();
}
}, [token])
const data = {
userData,
isLoading,
isError
}
return data
}
Кроме того, поскольку useParseToken возвращает токен, вам не нужно деструктурировать его при использовании
const token = useParseToken();
Привет @FedericoCastro, взгляните на новый API контекста. Похоже, это было бы идеально для вашего случая использования! Частью хуков был хук
useContext, который упрощает работу с контекстом!