Как я могу вернуть данные из пользовательского крючка react?

#reactjs #react-hooks

Вопрос:

У меня есть пользовательский крюк react, который извлекает данные из api. Я получаю ошибку: «Инвариантное нарушение: Недопустимый вызов крючка. Крючки могут вызываться только внутри тела функционального компонента.»

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

Вот мой собственный крючок:

 import { useState, useEffect } from "react"; const axios = require('axios'); const crypto = require('crypto');  function useFetchNGSData(endpoint) {  const[data, setData] = useState(null);   const dateString = () =gt; {  // MORE CODE  return date.toString();  }   const ngs_username = process.env.REACT_APP_NGS_USERNAME;  const ngs_password = process.env.REACT_APP_NGS_PASSWORD;  const ngs_access_token = process.env.REACT_APP_NGS_ACCESS_TOKEN;  const ngs_secret_key = process.env.REACT_APP_NGS_SECRET_KEY;    const string_to_sign = ngs_username   ngs_password   ngs_access_token   dateString();  const digest = crypto.createHmac('sha1', ngs_secret_key).update(string_to_sign).digest('base64');  const authKey = 'NGS '   ngs_access_token   ':'   digest;    const url = 'https://api.ngs.com';   useEffect(() =gt; {  axios.defaults.headers.common['Authorization'] = authKey;  axios.get(url   endpoint)  .then((response) =gt; {  setData(response.data);  })  .catch((error) =gt; {  console.log(error);  })  },[endpoint]);   return { data }; }  export default useFetchNGSData;  

Вот компонент, который использует пользовательский крюк:

 import React, { useState } from 'react'; import useFetchNGSData from '../useFetchNGSData';  const Data = (props) =gt; {  const [players, setPlayers] = useState([]);   const handleGetPlayers = () =gt; {  teamCollection.forEach(teamId =gt; {   setPlayers(useFetchNGSData('/league/roster/current?teamId=5100')  });  }   return (  lt;divgt;  // ... handleGetPlayers  lt;/divgt;  ); }  export default Data;  

Я знаю, что опускаю много кода, но, надеюсь, этого достаточно, чтобы продемонстрировать проблему.

Ответ №1:

Вам нужно переместить крючок из обработчика событий в тело компонента.

 import React, { useState } from 'react'; import useFetchNGSData from '../useFetchNGSData';  const Data = (props) =gt; {  const { data: players } = useFetchNGSData('/league/roster/current?teamId=5100')  return (  lt;divgt;  // ... handleGetPlayers  lt;/divgt;  ); }  export default Data;  

Но на самом деле вам не нужно использовать здесь сетплееры. У вас уже есть эти данные в возвращаемых значениях из вашего пользовательского крючка.

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

1. Мои сетплееры на самом деле находятся в цикле — я обновил приведенный выше код — каждый раз, когда в коллекцию команд добавляется новая команда. Меняет ли это способ вызова useFetchNGSData?

2. Нет, крючок всегда должен вызываться непосредственно в теле рендеринга компонента. Но если вам нужно извлекать новое значение из крючка для каждой итерации на основе предыдущей операции набора, вам нужно будет сделать несколько вещей, чтобы это сработало. Вероятно, самый простой способ извлечь функцию «добытчика» из крючка и заставить крючок использовать эту функцию добытчика, а затем импортировать как крючок, так и добытчик. Затем вы можете вызвать геттер в своем цикле. В качестве альтернативы вы можете рассмотреть возможность предоставления сеттера из вашего крючка, который будет принимать массив и выполнять итерацию внутри крючка.

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

4. Я думаю, что это немного выше моего понимания. Можете ли вы привести пример?