在事件处理程序中从localStorage获取数据时,不会呈现组件



在事件处理程序中,当从localStorage获取数据并将该数据分配给状态变量时,组件不会重新呈现以反映新值

逻辑是验证localStorage是否存在以及是否有当前id的数据,然后从localStorage为状态变量赋值,否则从端点获取数据并同步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;
}

原因是组件ShowDetailShowSummary接收isSummaryLoading的值作为属性,并且由于其值保持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>
);
}

感谢那些评论的人

最新更新