Gate article detail on a store-backed cache so the view paints once.
Sku page loads/caches the article before mounting ArticleView; the view reads sync from StorageManager instead of fetching again.
This commit is contained in:
@@ -7,6 +7,10 @@ import {
|
||||
buildCategoryPath,
|
||||
defaultCategoryPath,
|
||||
} from '../../pages/artikel/categoryRoute';
|
||||
import {
|
||||
artikelDetailPath,
|
||||
resolveArticleTab,
|
||||
} from '../../pages/artikel/articleRoute';
|
||||
|
||||
import ArticleTileTab from './ArticleTileTab';
|
||||
import ArticlePhotoTile from './ArticlePhotoTile';
|
||||
@@ -17,28 +21,55 @@ import ArticleViewEANs from './boxes/ArticleViewEANs';
|
||||
import ArticleViewPrice from './boxes/ArticleViewPrice';
|
||||
import ArticleViewLists from './boxes/ArticleViewLists';
|
||||
|
||||
function viewStateFromStore(store, sku) {
|
||||
const categoryState = store.getCategoryState();
|
||||
return {
|
||||
article: store.getArticle(sku) ?? null,
|
||||
categories: categoryState?.categories ?? null,
|
||||
rootCategoryId: categoryState?.rootCategoryId ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
class ArticleView extends Component {
|
||||
static contextType = StorageManagerContext;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.state = viewStateFromStore(context, props.sku);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { sku, tab, navigate } = this.props;
|
||||
const { article } = this.state;
|
||||
|
||||
if (prevProps.sku !== sku) {
|
||||
this.setState(viewStateFromStore(this.context, sku));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!article) return;
|
||||
const resolved = resolveArticleTab(tab, article);
|
||||
if (tab !== resolved) {
|
||||
navigate(artikelDetailPath(article, resolved), { replace: true });
|
||||
}
|
||||
}
|
||||
|
||||
refreshSearchCaches = () => {
|
||||
void this.context.updateArticleIndex();
|
||||
void this.context.updateCategoryTree();
|
||||
};
|
||||
|
||||
handleArticleUpdated = (next) => {
|
||||
this.props.onArticleUpdated?.(next);
|
||||
this.context.setArticle(next);
|
||||
this.setState({ article: next });
|
||||
this.refreshSearchCaches();
|
||||
};
|
||||
|
||||
handleArticleDeleted = () => {
|
||||
const {
|
||||
article: articleData,
|
||||
navigate,
|
||||
categories,
|
||||
rootCategoryId,
|
||||
} = this.props;
|
||||
const { navigate } = this.props;
|
||||
const { article, categories, rootCategoryId } = this.state;
|
||||
this.refreshSearchCaches();
|
||||
const categoryId = articleData.categoryIds?.[0];
|
||||
const categoryId = article?.categoryIds?.[0];
|
||||
if (categories && rootCategoryId != null && categoryId != null) {
|
||||
navigate(buildCategoryPath(categories, rootCategoryId, categoryId));
|
||||
return;
|
||||
@@ -46,19 +77,25 @@ class ArticleView extends Component {
|
||||
navigate(defaultCategoryPath());
|
||||
};
|
||||
|
||||
handleTabChange = (nextTab) => {
|
||||
const { navigate } = this.props;
|
||||
const { article } = this.state;
|
||||
navigate(artikelDetailPath(article, nextTab));
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
article: articleData,
|
||||
tab,
|
||||
onTabChange,
|
||||
categories,
|
||||
rootCategoryId,
|
||||
} = this.props;
|
||||
const { tab } = this.props;
|
||||
const { article, categories, rootCategoryId } = this.state;
|
||||
|
||||
if (!article || categories == null || rootCategoryId == null) return null;
|
||||
|
||||
const resolvedTab = resolveArticleTab(tab, article);
|
||||
if (tab !== resolvedTab) return null;
|
||||
|
||||
return (
|
||||
<PanelTileGrid>
|
||||
<ArticleViewName
|
||||
article={articleData}
|
||||
article={article}
|
||||
categories={categories}
|
||||
rootCategoryId={rootCategoryId}
|
||||
onArticleUpdated={this.handleArticleUpdated}
|
||||
@@ -68,24 +105,24 @@ class ArticleView extends Component {
|
||||
wide={1}
|
||||
tileKey={PANEL_TILE_KEYS.photo}
|
||||
sx={{ minHeight: 0 }}
|
||||
article={articleData}
|
||||
article={article}
|
||||
onArticleUpdated={this.handleArticleUpdated}
|
||||
/>
|
||||
|
||||
<ArticleViewStock article={articleData} />
|
||||
<ArticleViewStock article={article} />
|
||||
|
||||
<ArticleViewBrand
|
||||
article={articleData}
|
||||
article={article}
|
||||
onArticleUpdated={this.handleArticleUpdated}
|
||||
/>
|
||||
|
||||
<ArticleViewEANs
|
||||
article={articleData}
|
||||
article={article}
|
||||
onArticleUpdated={this.handleArticleUpdated}
|
||||
/>
|
||||
|
||||
<ArticleViewPrice
|
||||
article={articleData}
|
||||
article={article}
|
||||
onArticleUpdated={this.handleArticleUpdated}
|
||||
/>
|
||||
|
||||
@@ -93,13 +130,13 @@ class ArticleView extends Component {
|
||||
wide={3}
|
||||
tileKey={PANEL_TILE_KEYS.content}
|
||||
minHeight={200}
|
||||
article={articleData}
|
||||
tab={tab}
|
||||
onTabChange={onTabChange}
|
||||
article={article}
|
||||
tab={resolvedTab}
|
||||
onTabChange={this.handleTabChange}
|
||||
onArticleDeleted={this.handleArticleDeleted}
|
||||
/>
|
||||
|
||||
<ArticleViewLists article={articleData} />
|
||||
<ArticleViewLists article={article} />
|
||||
</PanelTileGrid>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user