Solid Start does not load images on load event?

import { Show, createEffect, createSignal } from "solid-js";

interface LazyImageProps {
placeholder?: string;
class?: string;
src: string;
alt: string;
}

export default function LazyImage(props: LazyImageProps) {
const [loading, setLoading] = createSignal(true);

createEffect(() => {
console.log("loading", loading());
});

const onLoad = (e: any) => {
console.log(e);
setLoading(false);
};

return (
<>
<Show when={loading() && props.placeholder}>
<img
src={props.placeholder}
class={props.class}
draggable="false"
alt="placeholder"
loading="lazy"
/>
</Show>
<img
onLoad={onLoad}
class={props.class}
draggable="false"
src={props.src}
alt={props.alt}
loading="lazy"
/>
</>
);
}
import { Show, createEffect, createSignal } from "solid-js";

interface LazyImageProps {
placeholder?: string;
class?: string;
src: string;
alt: string;
}

export default function LazyImage(props: LazyImageProps) {
const [loading, setLoading] = createSignal(true);

createEffect(() => {
console.log("loading", loading());
});

const onLoad = (e: any) => {
console.log(e);
setLoading(false);
};

return (
<>
<Show when={loading() && props.placeholder}>
<img
src={props.placeholder}
class={props.class}
draggable="false"
alt="placeholder"
loading="lazy"
/>
</Show>
<img
onLoad={onLoad}
class={props.class}
draggable="false"
src={props.src}
alt={props.alt}
loading="lazy"
/>
</>
);
}
Why the load event does not work? I still get true after loading the image.
8 Replies
peerreynders
peerreynders2mo ago
Seems to work fine: https://playground.solidjs.com/anonymous/06c22626-5476-4cb4-b75c-f9a3b826c236 I think you need to accomplish it with a single <img /> element. Have the onLoad change the src once the placeholder is loaded. The browser will leave the placeholder in place until the real image is loaded.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
peerreynders
peerreynders2mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Jason.json
Jason.jsonOP2mo ago
Ok thank you
Jason.json
Jason.jsonOP2mo ago
does not work
No description
Jason.json
Jason.jsonOP2mo ago
It stays like that maybe that's ssr problem?
Jason.json
Jason.jsonOP2mo ago
import { createSignal } from "solid-js";

interface LazyImageProps {
placeholder?: string;
class?: string;
src: string;
alt: string;
}

export default function LazyImage(props: LazyImageProps) {
const [source, setSource] = createSignal(props.placeholder);

const onLoad = () => {
console.log("lazy loading the image...");
if (source() === props.src) return;
setSource(props.src);
};

return (
<>
<img
src={source()}
onLoad={onLoad}
alt={props.alt}
class={props.class}
draggable="false"
loading="lazy"
/>
</>
);
}
import { createSignal } from "solid-js";

interface LazyImageProps {
placeholder?: string;
class?: string;
src: string;
alt: string;
}

export default function LazyImage(props: LazyImageProps) {
const [source, setSource] = createSignal(props.placeholder);

const onLoad = () => {
console.log("lazy loading the image...");
if (source() === props.src) return;
setSource(props.src);
};

return (
<>
<img
src={source()}
onLoad={onLoad}
alt={props.alt}
class={props.class}
draggable="false"
loading="lazy"
/>
</>
);
}
It does not even log the fired event. I also use workbox to cache images
No description
peerreynders
peerreynders2mo ago
I also use workbox to cache images
I wonder whether you're experiencing a race condition; given that the images are cached, perhaps they are loaded before the event handler is even added to the <img /> element. So you may need to delay setting the src until it is certain that the handler is installed. Try something like this: https://playground.solidjs.com/anonymous/d0b41fd4-e7cb-4969-b1ed-0cace34cf620
function LazyImage(props: LazyImageProps) {
const [source, setSource] = createSignal(props.placeholder ?? props.src);

const onLoad = () => {
console.log('lazy loading the image...');
setSource(props.src);
};

return (
<img
ref={(el) => {
if (el.complete) setSource(props.src);
}}
src={source()}
onLoad={onLoad}
alt={props.alt}
class={props.class}
draggable="false"
loading="lazy"
/>
);
}
function LazyImage(props: LazyImageProps) {
const [source, setSource] = createSignal(props.placeholder ?? props.src);

const onLoad = () => {
console.log('lazy loading the image...');
setSource(props.src);
};

return (
<img
ref={(el) => {
if (el.complete) setSource(props.src);
}}
src={source()}
onLoad={onLoad}
alt={props.alt}
class={props.class}
draggable="false"
loading="lazy"
/>
);
}
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Jason.json
Jason.jsonOP2mo ago
i used this freaky solution wich seems to work for me
import { createEffect, createSignal } from "solid-js";
import "./LazyImage.tsx.scss";
interface LazyImageProps {
placeholder?: string;
class?: string;
src: string;
alt: string;
}

export default function LazyImage(props: LazyImageProps) {
const [source, setSource] = createSignal(props.placeholder ?? props.src);
const [loading, setLoading] = createSignal(props.placeholder ? true : false);

let el: HTMLImageElement | undefined;

createEffect(() => {
if (el && el.complete) {
el.src = source();
el.onload = () => {
setLoading(false);
};
}
});

const onLoad = () => {
setSource(props.src);
};

return (
<img
classList={{ lazy: loading() }}
class={props.class}
ref={el}
src={source()}
onLoad={onLoad}
alt={props.alt}
draggable="false"
loading="lazy"
/>
);
}
import { createEffect, createSignal } from "solid-js";
import "./LazyImage.tsx.scss";
interface LazyImageProps {
placeholder?: string;
class?: string;
src: string;
alt: string;
}

export default function LazyImage(props: LazyImageProps) {
const [source, setSource] = createSignal(props.placeholder ?? props.src);
const [loading, setLoading] = createSignal(props.placeholder ? true : false);

let el: HTMLImageElement | undefined;

createEffect(() => {
if (el && el.complete) {
el.src = source();
el.onload = () => {
setLoading(false);
};
}
});

const onLoad = () => {
setSource(props.src);
};

return (
<img
classList={{ lazy: loading() }}
class={props.class}
ref={el}
src={source()}
onLoad={onLoad}
alt={props.alt}
draggable="false"
loading="lazy"
/>
);
}
It does not swap the placeholder image in this case and idk why It seems like it should work but it doesn't

Did you find this page helpful?