状态不会使用Axios的useEffect更新

时间:2019-10-03 02:37:56

标签: javascript reactjs

我正在构建一个简单的组件,该组件接收一个单词并将其向后发送,然后,它获取新单词,发送给字典API并显示结果。我创建了一个isLoading状态和一个error状态。当我得到不同于200的响应时,错误应该为true。但是在我的代码中,这没有发生。因此,当我得到不同于200的响应时,代码将尝试呈现{dictionaryData.entry.sense[1].def}并崩溃。

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;

很抱歉有任何错误,我只是想了解钩子。

1 个答案:

答案 0 :(得分:1)

我对您的代码进行了一些更改。

我将isLoading的默认值设置为false,这更有意义。

我用try catch包装了“ await axios”,以处理所有类型的错误。

你能检查一下吗?

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;