S
SolidJS17mo ago
ali

noUiSlider rerenders when moving slider

Hello, I have an issue with noUiSlider(https://refreshless.com/nouislider/) i want to make a slider with 2 knobs. Everytime i move a knob on the slider, i get the following error message in the console. Uncaught Error: noUiSlider: Slider was already initialized. the code looks like this
import { createEffect, createSignal, onCleanup } from "solid-js";
import "nouislider/dist/nouislider.css";
import noUiSlider from "nouislider";

function Slider() {
const [sliderValue, setSliderValue] = createSignal<[number, number]>([
20, 80,
]);
let sliderContainer: HTMLDivElement | null = null;

// Initialize the slider when the component mounts
createEffect(() => {
if (sliderContainer) {
noUiSlider.create(sliderContainer, {
start: sliderValue(),
connect: true,
range: {
min: 0,
max: 100,
},
});

// Update sliderValue state when the slider changes
sliderContainer.noUiSlider.on("update", (values: string[]) => {
setSliderValue([parseFloat(values[0]), parseFloat(values[1])]);
});
}

return () => {
if (sliderContainer) {
sliderContainer.noUiSlider.destroy();
}
};
});

return (
<div class="slider">
<div ref={(el) => (sliderContainer = el)}></div>
<p>
Slider Values: {sliderValue()[0]} - {sliderValue()[1]}
</p>
</div>
);
}

export default Slider;
import { createEffect, createSignal, onCleanup } from "solid-js";
import "nouislider/dist/nouislider.css";
import noUiSlider from "nouislider";

function Slider() {
const [sliderValue, setSliderValue] = createSignal<[number, number]>([
20, 80,
]);
let sliderContainer: HTMLDivElement | null = null;

// Initialize the slider when the component mounts
createEffect(() => {
if (sliderContainer) {
noUiSlider.create(sliderContainer, {
start: sliderValue(),
connect: true,
range: {
min: 0,
max: 100,
},
});

// Update sliderValue state when the slider changes
sliderContainer.noUiSlider.on("update", (values: string[]) => {
setSliderValue([parseFloat(values[0]), parseFloat(values[1])]);
});
}

return () => {
if (sliderContainer) {
sliderContainer.noUiSlider.destroy();
}
};
});

return (
<div class="slider">
<div ref={(el) => (sliderContainer = el)}></div>
<p>
Slider Values: {sliderValue()[0]} - {sliderValue()[1]}
</p>
</div>
);
}

export default Slider;
Any idea what is wrong? Much appreciated.
noUiSlider - JavaScript Range Slider | Refreshless.com
noUiSlider is a lightweight, ARIA-accessible JavaScript range slider with multi-touch and keyboard support. Great for responsive designs, and no dependencies!
2 Replies
ali
aliOP17mo ago
I made it work with the help of chat gpt, lol. In case anybody is interested in the solution it looks like this:
import { createSignal, onCleanup, onMount } from "solid-js";
import noUiSlider from "nouislider";
import "./nouislider.css";

function DualSlider() {
const [sliderValues, setSliderValues] = createSignal<[number, number]>([
25, 75,
]);

const sliderRef = (element: HTMLElement | null) => {
if (element) {
onMount(() => {
noUiSlider.create(element, {
start: sliderValues(),
range: {
min: 0,
max: 100,
},
step: 1,
connect: true,
});

element.noUiSlider.on("update", (values) => {
const newValues = values.map((value) =>
parseFloat(value)
) as [number, number];
setSliderValues(newValues);
});
});

onCleanup(() => {
element.noUiSlider.destroy();
});
}
};

return (
<div class="slider">
<div id="dual-knob-slider" ref={sliderRef}></div>
<p>
Slider Values: {sliderValues()[0]} - {sliderValues()[1]}
</p>
</div>
);
}

export default DualSlider;
import { createSignal, onCleanup, onMount } from "solid-js";
import noUiSlider from "nouislider";
import "./nouislider.css";

function DualSlider() {
const [sliderValues, setSliderValues] = createSignal<[number, number]>([
25, 75,
]);

const sliderRef = (element: HTMLElement | null) => {
if (element) {
onMount(() => {
noUiSlider.create(element, {
start: sliderValues(),
range: {
min: 0,
max: 100,
},
step: 1,
connect: true,
});

element.noUiSlider.on("update", (values) => {
const newValues = values.map((value) =>
parseFloat(value)
) as [number, number];
setSliderValues(newValues);
});
});

onCleanup(() => {
element.noUiSlider.destroy();
});
}
};

return (
<div class="slider">
<div id="dual-knob-slider" ref={sliderRef}></div>
<p>
Slider Values: {sliderValues()[0]} - {sliderValues()[1]}
</p>
</div>
);
}

export default DualSlider;
foolswisdom
foolswisdom17mo ago
The issue with the original code is that it uses createEffect instead of onMount, and that it returns a cleanup function (like you would in react, but that doesn't work in solid) instead of using the onCleanup function In your corrected code, you fixed those issues, though you didn't need to use a ref function to fix it (though it's fine either way)
Want results from more Discord servers?
Add your server