问题描述
我遇到了一个奇怪的问题,其中 petData 最初以未定义的形式记录到控制台,几分钟后填充数据数组。我认为这与获取数据然后通过上下文发送它所需的时间有关。问题是应用程序因错误“TypeError:无法访问属性“name”,petData[0] 未定义”而崩溃,我尝试使用 setTimeout 但这无济于事。有什么解决办法吗?
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
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 (
<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>
);
}
Context.js
import { createContext } from "react";
const PetDataContext = createContext([]);
export default PetDataContext;
解决方法
试试这个:
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..."
);
}
工作原理
这里的想法是,由于网络调用是同步的(它们同时运行,您无法判断它们何时执行),您只需观察 petData
状态,该状态将更新并显示 petData
时的实际内容{1}} 状态保存有效值。在那之前,您可以展示一些基本的加载程序,比如您在网站上看到的那种,可能是微调器或其他东西。
试试这个解决方案。修改您的 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");
});
}
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>
);
}