您可以使用异步函数通过 useState 设置初始状态吗

时间:2020-12-21 09:32:21

标签: javascript reactjs react-hooks

我的组件依赖于本地状态 (useState),但初始值应该来自 http 响应。

我可以传递一个异步函数来设置初始状态吗?如何从响应中设置初始状态?

这是我的代码

  const fcads = () => {
    let good;
    Axios.get(`/admin/getallads`).then((res) => {
      good = res.data.map((item) => item._id);
    });
    return good;
  };

  const [allads, setAllads] = useState(() => fcads());

但是当我尝试 console.log(allads) 时,我得到了结果 undefined

2 个答案:

答案 0 :(得分:0)

您可以使用自定义钩子在 use-state-with-callback npm 包中包含 useState 的回调函数。

npm install use-state-with-callback

对于您的情况:

import React from "react";
import Axios from "axios";
import useStateWithCallback from "use-state-with-callback";

export default function App() {
  const [allads, setAllads] = useStateWithCallback([], (allads) => {
    let good;
    Axios.get("https://fakestoreapi.com/products").then((res) => {
      good = res.data.map((item) => item.id);
      console.log(good);
      setAllads(good);
    });
  });

  return (
    <div className="App">
      <h1> {allads} </h1>
    </div>
  );
}


演示和代码:https://codesandbox.io/s/distracted-torvalds-s5c8c?file=/src/App.js

答案 1 :(得分:0)

如果您使用函数作为 useState 的参数它必须是同步的

您的示例显示的代码是异步 - 它使用仅在请求完成后设置值的承诺

您正在尝试在第一次呈现组件时加载数据 - 这是一个非常常见的用例,有许多库可以处理它,例如这些流行的选择:https://www.npmjs.com/package/react-async-hook 和 {{3} }.他们不仅会设置要显示的数据,还会为您提供一个标志供您使用并显示加载程序或在发生这种情况时显示错误

这基本上就是您必须异步设置初始状态时的设置方式

const [allads, setAllads] = useState([]);
const [loading, setLoading] = useState(false);

React.useEffect(() => {
  // Show a loading animation/message while loading
  setLoading(true);

  // Invoke async request
  Axios.get(`/admin/getallads`).then((res) => {
    const ads = res.data.map((item) => item._id);
    // Set some items after a successful response
    setAllAds(ads):
  })
  .catch(e => alert(`Getting data failed: ${e.message}`))
  .finally(() => setLoading(false))
// No variable dependencies means this would run only once after the first render
}, []);

useState 的初始值视为可以立即设置的原始值。您知道您将显示处理项目列表(数组),那么初始值应该是一个空数组。 useState 只接受一个函数来覆盖更昂贵的情况,否则会在每次渲染过程中进行评估。喜欢从本地/会话存储读取

const [allads, setAllads] = useState(() => {
  const asText = localStorage.getItem('myStoredList');
  const ads = asText ? JSON.parse(asText) : [];
  return ads;
});