I have this react component that has a simple form where, when you put a superhero name, it makes an axios get request to an API that responds successfully with json object with info of said hero. That info is stored in the state and then mapped through to create a grid. It used to work just fine as a class element so I started doing other parts of the app that have nothing to do with this part, but when i run the whole app again so check i get an hook call error in this component.
This is the seeker component, i did the class and the funcion version.
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 = () => {
const fetchData = (data) => {axios.get(`https://www.superheroapi.com/api.php/1589015884770221/search/${name}`)
.then((response) => {
localStorage.setItem("addHeroAction", true);
let results = response.data.results;
localStorage.setItem("matchedHeros", results);
}).catch((error) => {
console.log(error)
})
}
let matchedHeros = localStorage.getItem("matchedHeros") ? localStorage.getItem("matchedHeros") : [];
const gridRender = (response) =>{
if(response.length && response != undefined){
console.log(response)
return(
<div className="grid__background">
<div className="grid">
<div className="grid__box grid__top grid__top--container"></div>
<div className="grid__box grid__top grid__top--container"><h2>Name</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Intelligence</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Strenght</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Speed</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Durability</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Power</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Combat</h2></div>
<div className="grid__box grid__top grid__top--container"></div>
{response.map(hero => grid(hero, hero.id))}
</div>
</div>)
} else {
return (<div></div>)
}
}
return (
<div>
<h1>Find your next teammate!</h1>
<Formik
initialValues={{ name: ''}}
validate={values => {
const errors = {};
if (!values.name) {
errors.name = 'Required';
} else if (
!/^[a-zA-Z]*$/.test(values.name)
) {
errors.name = 'Invalid name';
}
return errors;
}}
onSubmit={(values) => {
console.log(fetchData(values.name));
}}
>
{() => (
<Form>
<Field type="text" name="name" />
<ErrorMessage name="name" component="div" />
<button type="submit">
Submit
</button>
</Form>
)}
</Formik>
{gridRender(matchedHeros)}
</div>
)
} */
class Seeker extends React.Component{
state = {
matchedHeros : [],
loadingData : true
}
constructor(){
super();
this.fetchData = this.fetchData.bind(this);
}
fetchData = async (name) => {
if(this.state.loadingData){
await axios.get(`https://www.superheroapi.com/api.php/1589015884770221/search/${name}`)
.then((response) => {
localStorage.setItem("addHeroAction", true);
this.setState({matchedHeros : response.data.results, loadingData : false});
}).catch((error) => {
console.log(error)
})
}
}
render(){
return (
<div>
<h1>Find your next teammate!</h1>
<Formik
initialValues={{ name: ''}}
validate={values => {
const errors = {};
if (!values.name) {
errors.name = 'Required';
} else if (
!/^[a-zA-Z]*$/.test(values.name)
) {
errors.name = 'Invalid name';
}
return errors;
}}
onSubmit={(values) => {
this.fetchData(values.name);
}}
>
{() => (
<Form>
<Field type="text" name="name" />
<ErrorMessage name="name" component="div" />
<button type="submit">
Submit
</button>
</Form>
)}
</Formik>
{console.log(this.state.matchedHeros)}
{this.state.matchedHeros.length ?
(
<div className="grid__background">
<div className="grid">
<div className="grid__box grid__top grid__top--container"></div>
<div className="grid__box grid__top grid__top--container"><h2>Name</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Intelligence</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Strenght</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Speed</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Durability</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Power</h2></div>
<div className="grid__box grid__top grid__top--container"><h2>Combat</h2></div>
<div className="grid__box grid__top grid__top--container"></div>
</div>
</div>
)
:
<div></div>
}
{this.state.matchedHeros.map(hero => grid(hero, hero.id))}
</div>
)
}
}
export default Seeker;
It uses the formik library to verified the values and the it maps the info with a Grid component that works just fine on its own, so the problem is in this component. The axios call also sets a value in localStorage that i need to be set when the button is clicked.
The original was the class component but with it I have this error on the console.
“Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component.”
Then i made the functional component version, which is commented in the code above, but with it i can’t get the state updated with axios.
When i look into someone else’s examples they look like mine but I still get the hook call error, i already checked that i have up-to-date versions of react so that’s not the problem.
What am I doing wrong? or else, what suggestion can you guys give me to achieve the same result?