Reputation: 1792
I'm building a simple component that receives a word and send it backwards, then, it gets the new word, sends to a dictionary API and shows the result. I have created a isLoading
state and error
State. When i get a response different from 200, error should be true. But in my code, this is not happening. So, when i get a response different from 200, the code tries to render {dictionaryData.entry.sense[1].def}
and crashes.
import React, { useState, useEffect, useRef } from "react";
import axios from "axios";
import "./App.css";
function App() {
const [anagram, setAnagram] = useState("");
const [anagramResult, setAnagramResult] = useState("");
const [dictionaryData, setDictionaryData] = useState({});
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(false);
const isFirstRun = useRef(true);
useEffect(() => {
if (isFirstRun.current) {
isFirstRun.current = false; //i'm using useRef to not run this code on the first run
return;
}
const fetchData = async () => {
const result = await axios(
`http://dicionario-aberto.net/search-json/${anagramResult}`
);
if (result.status === 200) {
setDictionaryData(result.data);
console.log(result.data);
setIsLoading(false);
setError(false);
} else {
setError(true);
setIsLoading(true);
}
};
fetchData();
}, [anagramResult]);
const reverseWord = word => {
setAnagramResult([...word].reverse().join``);
};
return (
<div className="App">
<input
type="text"
name="anagram"
onChange={e => setAnagram(e.target.value)}
value={anagram}
/>
<button onClick={() => reverseWord(anagram)}>Check Anagram</button>
<p>result: {anagramResult}</p>
{isLoading ? null : (
<div>
<p>Definições: {dictionaryData.entry.sense[1].def}</p>
<p>{dictionaryData.entry.sense[2].def}</p>
<p>{dictionaryData.entry.sense[3].def}</p>
</div>
)}
{error ? <p>Houve um erro na pesquisa ou a palavra não existe.</p> : null}
</div>
);
}
export default App;
Sorry for any mistake, i'm just trying to understand hooks.
Upvotes: 2
Views: 552
Reputation: 17858
I made some changes to your code.
I set isLoading default value to false, that makes more sense.
I wrapped "await axios" with try catch to handle all kind of errors.
Can you check please?
import React, { useState, useEffect, useRef } from "react";
import axios from "axios";
import "./App.css";
function App() {
const [anagram, setAnagram] = useState("");
const [anagramResult, setAnagramResult] = useState("");
const [dictionaryData, setDictionaryData] = useState({});
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(false);
const isFirstRun = useRef(true);
useEffect(() => {
if (isFirstRun.current) {
isFirstRun.current = false; //i'm using useRef to not run this code on the first run
return;
}
const fetchData = async () => {
setIsLoading(true);
try {
const result = await axios.get(
`http://dicionario-aberto.net/search-json/${anagramResult}`
);
setIsLoading(false);
if (result.status === 200) {
setDictionaryData(result.data);
setError(false);
} else {
setDictionaryData({});
setError(true);
}
} catch (error) {
setDictionaryData({});
setError(true);
setIsLoading(false);
}
};
fetchData();
}, [anagramResult]);
const reverseWord = word => {
setAnagramResult([...word].reverse().join``);
};
return (
<div className="App">
<input
type="text"
name="anagram"
onChange={e => setAnagram(e.target.value)}
value={anagram}
/>
<button onClick={() => reverseWord(anagram)}>Check Anagram</button>
<p>result: {anagramResult}</p>
{isLoading && <p>Loading...</p>}
{!isLoading && dictionaryData.entry && (
<div>
<p>Definições: {dictionaryData.entry.sense[1].def}</p>
<p>{dictionaryData.entry.sense[2].def}</p>
<p>{dictionaryData.entry.sense[3].def}</p>
</div>
)}
{error ? <p>Houve um erro na pesquisa ou a palavra não existe.</p> : null}
</div>
);
}
export default App;
Upvotes: 1