为什么在useEffect中的函数内部使用setItems函数(useState钩子),而在useEffect中直接使用该函数,为什么不起作用?

时间:2020-07-06 13:53:15

标签: reactjs use-state

在示例中,setItems为什么在这里工作:

import React, { useState, useEffect } from "react";
import axios from "axios";
import "./styles.css";

export default function App() {
  const [items, setItems] = useState([]);

  useEffect(() => {
    const fetchItems = async () => {
      const result = await axios.get(
        `https://www.breakingbadapi.com/api/characters`
      );
      setItems(result.data);
    };
    fetchItems();
  }, []);

  return (
    <div>
      {items.map(item => (
        <div key={item.char_id}>{item.name}</div>
      ))}
    </div>
  );
}

https://codesandbox.io/s/boring-butterfly-2upbp

但不在此处(相反,它返回的是TypeError项目未定义):

import React, { useState, useEffect } from "react";
import axios from "axios";
import "./styles.css";

export default function App() {
  const [items, setItems] = useState([]);

  useEffect(() => {
    const fetchItems = async () => {
      const result = await axios.get(
        `https://www.breakingbadapi.com/api/characters`
      );
      return result;
    };
    const result = fetchItems();
    setItems(result.data);
  }, []);

  return (
    <div>
      {items.map(item => (
        <div key={item.char_id}>{item.name}</div>
      ))}
    </div>
  );
}

https://codesandbox.io/s/compassionate-lake-7iji5

3 个答案:

答案 0 :(得分:3)

您必须使用then函数来获取结果。

fetchItems().then(result => setItems(result.data))

您在useEffect钩中声明了一个异步函数,因此fetchItems将返回一个Promise。但是由于useEffect函数参数不接受异步函数,因此最好在设置状态之前先解决Promise

答案 1 :(得分:1)

const fetchItems = async () => {
  const result = await axios.get(
    `https://www.breakingbadapi.com/api/characters`
  );
  return result;
};

const result = fetchItems(); // result is a promise.
setItems(result.data);

在上面的代码段中,fetchItems是一个异步函数,因此它返回一个promise。因此,当您使用result.data时,您尝试访问的是Promise上的data,而不是已解决的值。

答案 2 :(得分:1)

主要原因是因为fetchItems返回了一个承诺(异步/等待)。

但是还有另一个问题,因为您需要等待诺言得以解决,因此您需要将await添加到fetchItems中,但这不能完成,因为useEffect必须返回一个干净的功能。

正确:

import React, { useState, useEffect } from "react";
import axios from "axios";
import "./styles.css";

export default function App() {
  const [items, setItems] = useState([]);

  // Also it's valid to create it directly inside the useEffect
  const fetchItems = useCallback(async () => {
    const result = await axios.get(
        `https://www.breakingbadapi.com/api/characters`
    );
    setItems(result.data);
  }, [setItems])

  useEffect(() => {
    fetchItems();
  }, [fetchItems]);

  return (
    <div>
      {items.map(item => (
        <div key={item.char_id}>{item.name}</div>
      ))}
    </div>
  );
}

错误:

import React, { useState, useEffect } from "react";
import axios from "axios";
import "./styles.css";

export default function App() {
  const [items, setItems] = useState([]);

  // WRONG: useEffect is not a clean-up function.
  useEffect(async () => { 
    const fetchItems = async () => {
      const result = await axios.get(
        `https://www.breakingbadapi.com/api/characters`
      );
      return result;
    };
    const result = await fetchItems();
    setItems(result.data);
  }, []);

  return (
    <div>
      {items.map(item => (
        <div key={item.char_id}>{item.name}</div>
      ))}
    </div>
  );
}