Мой компонент зависит от локального состояния (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.info(allads)
я получил результат undefined
.
Я делаю кнопку и делаю onclick для console.info(allads) @MacOS
Используйте хук useEffect и вызовите сервер внутри него.
Кроме того, вы не можете использовать good = res.data
внутри обратного вызова и return good
снаружи. return
вызывается перед запуском обратного вызова. Как вернуть ответ при асинхронном вызове?
Я пытался, как вы сказали, но все еще не определился @adiga
Вы можете использовать пользовательский хук, чтобы включить функцию обратного вызова для useState
с пакетом use-state-with-callback npm.
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.info(good);
setAllads(good);
});
});
return (
<div className = "App">
<h1> {allads} </h1>
</div>
);
}
Демонстрация и код: https://codesandbox.io/s/distracted-torvalds-s5c8c?file=/src/App.js
Я действительно не знаю, как это использовать, вы можете привести пример?
@testtet - обновил мой ответ примером.
Извини, братан, ты уверен, что твой код не неверен? Я пытался, но все еще не определено
Да, это сработает. Я не уверен, каким будет ваш ответ API. Поэтому я использовал поддельный API, чтобы помочь вам. проверить - codeandbox.io/s/distracted-torvalds-s5c8c?file=/src/…
Если вы используете функцию в качестве аргумента для useState
, она должна быть синхронной.
Код, показанный в вашем примере, является асинхронным — он использует обещание, которое устанавливает значение только после завершения запроса.
Вы пытаетесь загрузить данные, когда компонент визуализируется в первый раз — это очень распространенный вариант использования, и существует множество библиотек, которые его обрабатывают, например эти популярные варианты: https://www.npmjs.com/package /react-async-hook и https://www.npmjs.com/package/@react-hook/async. Они не только установят данные для отображения, но и предоставят вам флаг для использования и отобразят загрузчик или отобразят ошибку, если это произошло.
Это в основном то, как вы устанавливаете начальное состояние, когда вам нужно установить его асинхронно.
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;
});
Где ты делал
console.info(allads)
?