#javascript #reactjs #react-hooks #axios #state
#язык JavaScript #реагирует на #реагируют-крючки #аксиос #государство
Вопрос:
У меня есть компонент react, который имеет простую форму, в которой, когда вы вводите имя супергероя, он отправляет запрос axios get в API, который успешно отвечает объектом json с информацией об указанном герое. Эта информация хранится в состоянии, а затем отображается для создания сетки. Раньше он отлично работал как элемент класса, поэтому я начал выполнять другие части приложения, которые не имеют ничего общего с этой частью, но когда я снова запускаю все приложение, поэтому проверьте, что я получаю ошибку вызова в этом компоненте.
Это компонент искателя, я сделал версию класса и функции.
import React, { useState } from "react"; import { Formik, Form, Field, ErrorMessage } from 'formik'; import axios from "axios"; require("babel-core/register"); require("babel-polyfill"); import grid from "../components/grid"; /* const Seeker = () =gt; { const fetchData = (data) =gt; {axios.get(`https://www.superheroapi.com/api.php/1589015884770221/search/${name}`) .then((response) =gt; { localStorage.setItem("addHeroAction", true); let results = response.data.results; localStorage.setItem("matchedHeros", results); }).catch((error) =gt; { console.log(error) }) } let matchedHeros = localStorage.getItem("matchedHeros") ? localStorage.getItem("matchedHeros") : []; const gridRender = (response) =gt;{ if(response.length amp;amp; response != undefined){ console.log(response) return( lt;div className="grid__background"gt; lt;div className="grid"gt; lt;div className="grid__box grid__top grid__top--container"gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Namelt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Intelligencelt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Strenghtlt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Speedlt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Durabilitylt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Powerlt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Combatlt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;/divgt; {response.map(hero =gt; grid(hero, hero.id))} lt;/divgt; lt;/divgt;) } else { return (lt;divgt;lt;/divgt;) } } return ( lt;divgt; lt;h1gt;Find your next teammate!lt;/h1gt; lt;Formik initialValues={{ name: ''}} validate={values =gt; { const errors = {}; if (!values.name) { errors.name = 'Required'; } else if ( !/^[a-zA-Z]*$/.test(values.name) ) { errors.name = 'Invalid name'; } return errors; }} onSubmit={(values) =gt; { console.log(fetchData(values.name)); }} gt; {() =gt; ( lt;Formgt; lt;Field type="text" name="name" /gt; lt;ErrorMessage name="name" component="div" /gt; lt;button type="submit"gt; Submit lt;/buttongt; lt;/Formgt; )} lt;/Formikgt; {gridRender(matchedHeros)} lt;/divgt; ) } */ class Seeker extends React.Component{ state = { matchedHeros : [], loadingData : true } constructor(){ super(); this.fetchData = this.fetchData.bind(this); } fetchData = async (name) =gt; { if(this.state.loadingData){ await axios.get(`https://www.superheroapi.com/api.php/1589015884770221/search/${name}`) .then((response) =gt; { localStorage.setItem("addHeroAction", true); this.setState({matchedHeros : response.data.results, loadingData : false}); }).catch((error) =gt; { console.log(error) }) } } render(){ return ( lt;divgt; lt;h1gt;Find your next teammate!lt;/h1gt; lt;Formik initialValues={{ name: ''}} validate={values =gt; { const errors = {}; if (!values.name) { errors.name = 'Required'; } else if ( !/^[a-zA-Z]*$/.test(values.name) ) { errors.name = 'Invalid name'; } return errors; }} onSubmit={(values) =gt; { this.fetchData(values.name); }} gt; {() =gt; ( lt;Formgt; lt;Field type="text" name="name" /gt; lt;ErrorMessage name="name" component="div" /gt; lt;button type="submit"gt; Submit lt;/buttongt; lt;/Formgt; )} lt;/Formikgt; {console.log(this.state.matchedHeros)} {this.state.matchedHeros.length ? ( lt;div className="grid__background"gt; lt;div className="grid"gt; lt;div className="grid__box grid__top grid__top--container"gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Namelt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Intelligencelt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Strenghtlt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Speedlt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Durabilitylt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Powerlt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;h2gt;Combatlt;/h2gt;lt;/divgt; lt;div className="grid__box grid__top grid__top--container"gt;lt;/divgt; lt;/divgt; lt;/divgt; ) : lt;divgt;lt;/divgt; } {this.state.matchedHeros.map(hero =gt; grid(hero, hero.id))} lt;/divgt; ) } } export default Seeker;
Он использует библиотеку formik для проверки значений, и он сопоставляет информацию с компонентом сетки, который отлично работает сам по себе, поэтому проблема в этом компоненте. Вызов axios также устанавливает значение в localStorage, которое мне нужно установить при нажатии кнопки.
Оригиналом был компонент класса, но с ним у меня эта ошибка на консоли.
«Неперехваченная ошибка: Недопустимый вызов соединения. Крючки могут вызываться только внутри тела функционального компонента.»
Затем я создал версию функционального компонента, которая прокомментирована в приведенном выше коде, но с ее помощью я не могу обновить состояние с помощью axios.
Когда я смотрю на чужие примеры, они выглядят как мои, но я все равно получаю ошибку вызова крючка, я уже проверил, что у меня есть обновленные версии react, так что это не проблема. Что я делаю не так? или еще, что вы, ребята, можете мне посоветовать, чтобы добиться того же результата?
Ответ №1:
Если вы хотите получить героев при первоначальном монтаже компонента:
import React, { useState, useEffect } from "react"; async function getHeros(name) { return axios.get( `https://www.superheroapi.com/api.php/1589015884770221/search/${name}` ); } const Seeker = () =gt; { const [heros, setHeros] = useState([]); useEffect(() =gt; { getHeros('someName').then((heros) =gt; { console.log('heros: ', heros); setHeros(heros); localStorage.setItem("matchedHeros", heros); }, console.error); }, []); return ( lt;divgt; {heros.map((hero, i) =gt; ( lt;spangt;{hero}lt;/spangt; ))} lt;/divgt; ); }
Комментарии:
1. Спасибо за вашу помощь! это действительно работает, но не для той цели, которую я искал. Как я могу сделать это таким образом, чтобы при отправке имени героя (которое написано пользователем во входных данных) вызов getHeros получал значение и выполнял поиск с его помощью? Потому что, если я попытаюсь поместить вызов useEffect в другую функцию, а затем вызвать указанную функцию, когда я отправлю форму, я получу ту же ошибку от formik, который вводит недопустимые вызовы крючков.
2. Эффект использования находится в корне компонента, а не внутри произвольных функций. Его основное применение-в качестве дескрипторов жизненного цикла при первоначальном монтаже компонента или при его обновлении. Здесь [] в конце эффекта использования делает его похожим на ‘componentDidMount для компонентов на основе классов. Чтобы выполнить то, что вы хотите, вам следует поискать в Google «получение данных при отправке реакции» для некоторых примеров кода. Хотя, я думаю, вам больше всего помогло бы посмотреть один или два урока на YouTube для создания простого проекта react.