Skip to content

Commit 8545ca7

Browse files
authored
fix: Infininite loop in backgrounds (#4299)
## Description Just inifinite loop fix ## Steps for reproduction 1. click button 2. expect xyz ## Code Review - [ ] hi @kof, I need you to do - conceptual review (architecture, feature-correctness) - detailed review (read every line) - test it on preview ## Before requesting a review - [ ] made a self-review - [ ] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [ ] tested locally and on preview environment (preview dev login: 5de6) - [ ] updated [test cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md) document - [ ] added tests - [ ] if any new env variables are added, added them to `.env` file
1 parent 32615ba commit 8545ca7

File tree

1 file changed

+61
-44
lines changed

1 file changed

+61
-44
lines changed

apps/builder/app/builder/features/style-panel/sections/backgrounds/background-image.tsx

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { InvalidValue } from "@webstudio-is/css-engine";
1+
import type { InvalidValue, StyleValue } from "@webstudio-is/css-engine";
22
import {
33
TextArea,
44
textVariants,
@@ -9,9 +9,8 @@ import {
99
Tooltip,
1010
Text,
1111
} from "@webstudio-is/design-system";
12-
import { useRef, useState, useEffect } from "react";
12+
import { useRef, useState } from "react";
1313
import type {} from "../../controls";
14-
import { useStore } from "@nanostores/react";
1514
import { $assets } from "~/shared/nano-states";
1615
import type { StyleUpdateOptions } from "../../shared/use-style-data";
1716
import { InfoCircleIcon } from "@webstudio-is/icons";
@@ -35,54 +34,72 @@ const isAbsoluteURL = (value: string) => {
3534
}
3635
};
3736

38-
export const BackgroundImage = ({ index }: { index: number }) => {
39-
const textAreaRef = useRef<HTMLTextAreaElement>(null);
40-
const assets = useStore($assets);
41-
const styleDecl = useComputedStyleDecl("backgroundImage");
42-
const styleValue = getRepeatedStyleItem(styleDecl, index);
43-
const [errors, setErrors] = useState<string[]>([]);
44-
const [intermediateValue, setIntermediateValue] = useState<
45-
IntermediateValue | InvalidValue | undefined
46-
>(undefined);
47-
48-
useEffect(() => {
49-
if (styleValue === undefined) {
50-
return;
37+
const getInitialErrors = (styleValue: StyleValue | undefined): string[] => {
38+
const assets = $assets.get();
39+
if (styleValue === undefined) {
40+
return [];
41+
}
42+
if (styleValue.type === "image") {
43+
if (styleValue.value.type === "asset") {
44+
const asset = assets.get(styleValue.value.value);
45+
if (asset === undefined || asset.type !== "image") {
46+
return [`Asset ${styleValue.value.value} is not found in project`];
47+
}
5148
}
49+
}
50+
return [];
51+
};
5252

53-
if (styleValue.type === "keyword") {
54-
setIntermediateValue({
55-
type: "intermediate",
56-
value: styleValue.value,
57-
});
58-
}
53+
const getInitialValue = (
54+
styleValue: StyleValue | undefined
55+
): IntermediateValue | InvalidValue | undefined => {
56+
const assets = $assets.get();
5957

60-
let backgroundUrl;
61-
if (styleValue.type === "image") {
62-
if (styleValue.value.type === "asset") {
63-
const asset = assets.get(styleValue.value.value);
64-
if (asset === undefined || asset.type !== "image") {
65-
setErrors(["Asset not found"]);
66-
setIntermediateValue({
67-
type: "invalid",
68-
value: styleValue.value.value,
69-
});
70-
return;
71-
}
72-
backgroundUrl = `url(${asset.name})`;
73-
}
58+
if (styleValue === undefined) {
59+
return;
60+
}
7461

75-
if (styleValue.value.type === "url") {
76-
backgroundUrl = `url(${styleValue.value.url})`;
62+
if (styleValue.type === "keyword") {
63+
return {
64+
type: "intermediate",
65+
value: styleValue.value,
66+
};
67+
}
68+
69+
let backgroundUrl;
70+
if (styleValue.type === "image") {
71+
if (styleValue.value.type === "asset") {
72+
const asset = assets.get(styleValue.value.value);
73+
if (asset === undefined || asset.type !== "image") {
74+
return {
75+
type: "invalid",
76+
value: styleValue.value.value,
77+
};
7778
}
79+
backgroundUrl = `url(${asset.name})`;
80+
}
7881

79-
setIntermediateValue(
80-
backgroundUrl !== undefined
81-
? { type: "intermediate", value: backgroundUrl }
82-
: undefined
83-
);
82+
if (styleValue.value.type === "url") {
83+
backgroundUrl = `url(${styleValue.value.url})`;
8484
}
85-
}, [styleValue, assets]);
85+
86+
return backgroundUrl !== undefined
87+
? { type: "intermediate", value: backgroundUrl }
88+
: undefined;
89+
}
90+
};
91+
92+
export const BackgroundImage = ({ index }: { index: number }) => {
93+
const textAreaRef = useRef<HTMLTextAreaElement>(null);
94+
95+
const styleDecl = useComputedStyleDecl("backgroundImage");
96+
const styleValue = getRepeatedStyleItem(styleDecl, index);
97+
const [errors, setErrors] = useState<string[]>(() =>
98+
getInitialErrors(styleValue)
99+
);
100+
const [intermediateValue, setIntermediateValue] = useState<
101+
IntermediateValue | InvalidValue | undefined
102+
>(() => getInitialValue(styleValue));
86103

87104
const handleChange = (value: string, options: StyleUpdateOptions) => {
88105
setIntermediateValue({

0 commit comments

Comments
 (0)