Reactjs 如何等待在react中填充数据?
我遇到了一个奇怪的问题,petData最初以未定义的形式记录到控制台,几分钟后填充数据数组。我假设这与获取数据然后通过上下文发送所需的时间有关。问题是应用程序正在崩溃,错误为“TypeError:无法访问属性”name,“petData[0]未定义”我尝试使用setTimeout,但没有帮助。有什么解决办法吗Reactjs 如何等待在react中填充数据?,reactjs,axios,fetch,react-context,use-context,Reactjs,Axios,Fetch,React Context,Use Context,我遇到了一个奇怪的问题,petData最初以未定义的形式记录到控制台,几分钟后填充数据数组。我假设这与获取数据然后通过上下文发送所需的时间有关。问题是应用程序正在崩溃,错误为“TypeError:无法访问属性”name,“petData[0]未定义”我尝试使用setTimeout,但没有帮助。有什么解决办法吗 function SearchPage() { const { petData } = useContext(PetDataContext); console.log(petDat
function SearchPage() {
const { petData } = useContext(PetDataContext);
console.log(petData[0].name);
const [filter, setFilter] = useState("");
const filteredData = useMemo(() => {
if (filter == "") return petData;
return petData.filter(
(item) =>
item.name.toLowerCase().includes(filter) ||
item.breed.toLowerCase().includes(filter)
);
}, [petData, filter]);
return (
<>
<SearchBar onSearch={(searchTerm) => setFilter(searchTerm)} />
<div className="d-flex flex-wrap sp-body">
<DogCardsDisplayed petData={filteredData} />
</div>
</>
);
}
export default SearchPage;
试试这个解决方案。修改你的
App.js
文件。我认为您遇到了竞争条件,您必须安装react async hook
import { useAsync } from 'react-async-hook';
function App() {
fetchPetData = () => {
return axios
.get(`${BACK_PORT}/data`)
.then(function (response) {
return response.data
})
.catch(function (error) {
console.log(error);
Swal.fire("Oops...", error.response.data, "error");
});
}
const value = useAsync(fetchPetData);
return (
<div className="App">
<PetDataContext.Provider value={{ value }}>
<BrowserRouter>
<NavBar />
<Switch>
<Route path="/" component={MainSignedOut} exact />
<Route path="/mainsignedin" component={MainSignedIn} />
<Route path="/searchpage" component={SearchPage} />
<Route path="/mypets" component={MyPets} />
<Route path="/admin" component={Admin} />
<Route exact path="/pets/:id" component={PetPage} />
<Route component={err404} />
</Switch>
</BrowserRouter>
</PetDataContext.Provider>
</div>
);
}
从'react async hook'导入{useAsync};
函数App(){
fetchPetData=()=>{
返回轴
.get(`${BACK\u PORT}/data`)
.然后(功能(响应){
返回响应.data
})
.catch(函数(错误){
console.log(错误);
Swal.fire(“Oops…”,error.response.data,“error”);
});
}
const value=useAsync(fetchPetData);
返回(
);
}
试试这个:
function App() {
const [petData, setPetData] = useState([]);
useEffect(() => {
axios
.get(`${BACK_PORT}/data`)
.then(function (response) {
setPetData(response.data);
})
.catch(function (error) {
console.log(error);
Swal.fire("Oops...", error.response.data, "error");
});
}, []);
console.log(petData);
return petData ? (
<div className="App">
<PetDataContext.Provider value={{ petData }}>
<BrowserRouter>
<NavBar />
<Switch>
<Route path="/" component={MainSignedOut} exact />
<Route path="/mainsignedin" component={MainSignedIn} />
<Route path="/searchpage" component={SearchPage} />
<Route path="/mypets" component={MyPets} />
<Route path="/admin" component={Admin} />
<Route exact path="/pets/:id" component={PetPage} />
<Route component={err404} />
</Switch>
</BrowserRouter>
</PetDataContext.Provider>
</div>
) : (
"Loading pets..."
);
}
函数应用程序(){
const[petData,setPetData]=useState([]);
useffect(()=>{
axios
.get(`${BACK\u PORT}/data`)
.然后(功能(响应){
setPetData(response.data);
})
.catch(函数(错误){
console.log(错误);
Swal.fire(“Oops…”,error.response.data,“error”);
});
}, []);
console.log(petData);
返回数据(
) : (
“装载宠物…”
);
}
工作原理
这里的想法是,由于网络调用是同步的(它们并发运行,您无法判断它们何时执行),因此您只需观察将被更新的
petData
状态,并在petData
状态持有有效值时显示实际内容。在此之前,您可以显示一些基本的加载程序,比如您在网站上看到的那种,可能是微调器或其他东西。您有多确定您需要上下文API来完成您要完成的任务?您正在尝试访问和记录petData[0]。name
在petData
之前包含任何数据。您希望编写的组件不尝试访问不存在的数据,并且可能会重写它以处理这种情况,并呈现某种回退UI,直到它具有要呈现的数据。因此,最好不要使用上下文吗?React文档禁止使用它,除非有必要,因为它增加了复杂性和一些性能考虑因素。请参阅。如果将初始状态更改为null而不是[],则此操作有效。谢谢很好,您还可以执行返回petData.length?():“加载”
如果必须将状态初始化为空数组。
import { useAsync } from 'react-async-hook';
function App() {
fetchPetData = () => {
return axios
.get(`${BACK_PORT}/data`)
.then(function (response) {
return response.data
})
.catch(function (error) {
console.log(error);
Swal.fire("Oops...", error.response.data, "error");
});
}
const value = useAsync(fetchPetData);
return (
<div className="App">
<PetDataContext.Provider value={{ value }}>
<BrowserRouter>
<NavBar />
<Switch>
<Route path="/" component={MainSignedOut} exact />
<Route path="/mainsignedin" component={MainSignedIn} />
<Route path="/searchpage" component={SearchPage} />
<Route path="/mypets" component={MyPets} />
<Route path="/admin" component={Admin} />
<Route exact path="/pets/:id" component={PetPage} />
<Route component={err404} />
</Switch>
</BrowserRouter>
</PetDataContext.Provider>
</div>
);
}
function App() {
const [petData, setPetData] = useState([]);
useEffect(() => {
axios
.get(`${BACK_PORT}/data`)
.then(function (response) {
setPetData(response.data);
})
.catch(function (error) {
console.log(error);
Swal.fire("Oops...", error.response.data, "error");
});
}, []);
console.log(petData);
return petData ? (
<div className="App">
<PetDataContext.Provider value={{ petData }}>
<BrowserRouter>
<NavBar />
<Switch>
<Route path="/" component={MainSignedOut} exact />
<Route path="/mainsignedin" component={MainSignedIn} />
<Route path="/searchpage" component={SearchPage} />
<Route path="/mypets" component={MyPets} />
<Route path="/admin" component={Admin} />
<Route exact path="/pets/:id" component={PetPage} />
<Route component={err404} />
</Switch>
</BrowserRouter>
</PetDataContext.Provider>
</div>
) : (
"Loading pets..."
);
}