简体   繁体   English

你可以使用异步 function 来设置初始 state 和 useState

[英]Can you use an async function to set initial state with useState

My component relies on local state ( useState ), but the initial value should come from an http response.我的组件依赖于本地 state ( useState ),但初始值应该来自 http 响应。

Can I pass an async function to set the initial state?我可以通过异步 function 来设置初始 state 吗? How can I set the initial state from the response?如何从响应中设置初始 state?

This is my code这是我的代码

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

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

But when I try console.log(allads) I got result undefined .但是当我尝试console.log(allads)时,我得到了结果undefined

If you use a function as an argument for useState it has to be synchronous .如果您使用 function 作为useState的参数,则它必须是同步的。

The code your example shows is asynchronous - it uses a promise that sets the value only after the request is completed您的示例显示的代码是异步的 - 它使用 promise 仅在请求完成后设置值

You are trying to load data when a component is rendered for the first time - this is a very common use case and there are many libraries that handle it, like these popular choices: https://www.npmjs.com/package/react-async-hook and https://www.npmjs.com/package/@react-hook/async .您正在尝试在第一次渲染组件时加载数据 - 这是一个非常常见的用例,有很多库可以处理它,比如这些流行的选择: https://www.npmjs.com/package/react -async-hookhttps://www.npmjs.com/package/@react-hook/async They would not only set the data to display, but provide you a flag to use and show a loader or display an error if such has happened他们不仅会设置要显示的数据,还会为您提供一个标志以使用并显示加载程序或在发生这种情况时显示错误

This is basically how you would set initial state when you have to set it asynchronously当您必须异步设置初始 state 时,这基本上就是设置它的方式

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
}, []);

Think of the initial value of useState as something raw that you can set immediately.useState的初始值视为可以立即设置的原始值。 You know you would be display handling a list (array) of items, then the initial value should be an empty array.您知道您将显示处理项目列表(数组),那么初始值应该是一个空数组。 useState only accept a function to cover a bit more expensive cases that would otherwise get evaluated on each render pass. useState仅接受 function 以涵盖更昂贵的情况,否则这些情况将在每次渲染过程中进行评估。 Like reading from local/session storage就像从本地/会话存储中读取

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

You can use the custom hook to include a callback function for useState with use-state-with-callback npm package.您可以使用自定义钩子为useState包含回调 function 和use-state-with-callback npm package。

npm install use-state-with-callback

For your case:对于您的情况:

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>
  );
}


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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM