javascript - 在事件处理程序中从 localStorage 获取数据时不呈现组件
问题描述
在事件处理程序中,当从状态变量获取数据localStorage
并将此数据分配给状态变量时,不会重新渲染组件以反映新值
逻辑是验证localStorage是否存在且当前id有数据,然后从localStorage给状态变量赋值,否则从endpoints获取数据并同步localStorage
如果满足这些条件,我会从 localStorage 获取数据并将值分配给状态变量,但组件不会重新渲染
if (hasLocalStorage() && existInLocalStorage(id)) {
const [show, episodes, cast] = fetchFromLocalStorage(id);
setShow(show);
setEpisodes(episodes);
setCast(cast);
return false;
}
这是完整的功能
function clickHandler(id) {
setIsSummaryLoading(true);
setHasSummaryLoadingErrors(false);
if (hasLocalStorage() && existInLocalStorage(id)) {
const [show, episodes, cast] = fetchFromLocalStorage(id);
setShow(show);
setEpisodes(episodes);
setCast(cast);
return false;
}
const endpoints = [
`/shows/${id}`,
`/shows/${id}/episodes`,
`/shows/${id}/cast`,
];
const promises = endpoints.map((endpoint) => fetcher(endpoint));
Promise.all(promises)
.then((data) => {
const [show, episodes, cast] = data;
setIsSummaryLoading(false);
syncLocalStorage({ id, data });
setShow(show);
setEpisodes(episodes);
setCast(cast);
})
.catch((error) => {
setHasSummaryLoadingErrors(true);
setIsSummaryLoading(false);
console.error(error.message);
});
}
其他相关功能如下
function syncLocalStorage({ id, data }) {
let storage = localStorage.maze ? JSON.parse(localStorage.maze) : {};
storage[id] = data;
localStorage.maze = JSON.stringify(storage);
}
function fetchFromLocalStorage(id) {
return JSON.parse(localStorage.maze)[id];
}
function hasLocalStorage() {
return localStorage.maze !== undefined;
}
function existInLocalStorage(id) {
return id in JSON.parse(localStorage.maze);
}
这是完整的组件代码
function App() {
const [show, setShow] = useState({});
const [episodes, setEpisodes] = useState([]);
const [cast, setCast] = useState(null);
const [shows, setShows] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [hasErrors, setHasErrors] = useState(false);
const [isSummaryLoading, setIsSummaryLoading] = useState(false);
const [hasSummaryLoadingErrors, setHasSummaryLoadingErrors] = useState(false);
function submitHandler(query) {
setIsLoading(true);
setHasErrors(false);
fetcher(`/search/shows?q=${query}`)
.then((shows) => {
const showList = shows.map((entry) => entry.show);
setIsLoading(false);
setShows(showList);
})
.catch((error) => {
setHasErrors(true);
setIsLoading(false);
console.error(error.message);
});
}
function clickHandler(id) {
setIsSummaryLoading(true);
setHasSummaryLoadingErrors(false);
if (hasLocalStorage() && existInLocalStorage(id)) {
const [show, episodes, cast] = fetchFromLocalStorage(id);
setShow(show);
setEpisodes(episodes);
setCast(cast);
return false;
}
const endpoints = [
`/shows/${id}`,
`/shows/${id}/episodes`,
`/shows/${id}/cast`,
];
const promises = endpoints.map((endpoint) => fetcher(endpoint));
Promise.all(promises)
.then((data) => {
const [show, episodes, cast] = data;
setIsSummaryLoading(false);
syncLocalStorage({ id, data });
setShow(show);
setEpisodes(episodes);
setCast(cast);
})
.catch((error) => {
setHasSummaryLoadingErrors(true);
setIsSummaryLoading(false);
console.error(error.message);
});
}
return (
<>
<div>
<Form onSubmit={submitHandler} />
{hasErrors ? <HasErrors /> : null}
{isLoading ? (
<IsLoading />
) : (
<Shows shows={shows} onClick={clickHandler} />
)}
</div>
<ShowDetail
show={show}
isSummaryLoading={isSummaryLoading}
hasSummaryLoadingErrors={hasSummaryLoadingErrors}
/>
<ShowSummary
episodes={episodes}
cast={cast}
isSummaryLoading={isSummaryLoading}
hasSummaryLoadingErrors={hasSummaryLoadingErrors}
/>
</>
);
}
感谢您的意见
解决方案
设置setIsSummaryLoading
状态变量false
解决问题
if (hasLocalStorage() && existInLocalStorage(id)) {
const [show, episodes, cast] = fetchFromLocalStorage(id);
setShow(show);
setEpisodes(episodes);
setCast(cast);
setIsSummaryLoading(false); // set to false
return false;
}
原因是组件ShowDetail
并ShowSummary
接收isSummaryLoading
as 属性的值,并且它的值保持不变true
<ShowDetail
show={show}
isSummaryLoading={isSummaryLoading}
hasSummaryLoadingErrors={hasSummaryLoadingErrors}
/>
<ShowSummary
episodes={episodes}
cast={cast}
isSummaryLoading={isSummaryLoading}
hasSummaryLoadingErrors={hasSummaryLoadingErrors}
/>
这是 ShowDetail 组件的代码,因为isSummaryLoading
被设置为true
仅<IsLoading />
被渲染
function ShowDetail({ show, isSummaryLoading, hasSummaryLoadingErrors }) {
return (
<div>
{hasSummaryLoadingErrors ? <HasErrors /> : null}
{isSummaryLoading ? (
<IsLoading />
) : (
<>
{Object.keys(show).length > 0 && (
<>
<h1>{show.name}</h1>
<img src={show.image && show.image.medium} alt={show.name} />
<p dangerouslySetInnerHTML={createMarkup(show.summary)} />
<ShowTable show={show} />
</>
)}
</>
)}
</div>
);
}
感谢评论的人
推荐阅读
- javascript - 如何覆盖 Datatables 上的数据?
- android - 在 RecyclerView.Adapter 中更改 textView 颜色
- c# - Task.Run(async) 递归的性能影响
- java - Weblogic - 为什么 Java ClassLoader 不从空清单 jar 中提到的 jar 加载类
- c# - C# ASP.NET Core Entity Framework Core 异步 ToQueryable 比较
- ios - AlamoFire5 空响应可解码
- hololens - HoloLens 2 无法使用 Microsoft HoloLens Windows 10 桌面应用程序连接
- c++ - 在 C++ 中读取外来字符
- git - 将 Bitbucket-Branch 同步到 GitHub 存储库
- javascript - Ajax 调用后的 Javascript SideBar 问题