I have a problem that when I use react-sortablejs with local images, the src to image is not display. The code:
import { useState } from "react";
import axios from "axios";
import { useRouter } from "next/router";
import Image from "next/image";
import Spinner from "./Spinner";
import { ReactSortable } from "react-sortablejs";
export default function ProductForm({
_id,
title: existingTitle,
description: existingDescription,
price: existingPrice,
images: existingImages,
}) {
const [title, setTitle] = useState(existingTitle || "");
const [description, setDescription] = useState(existingDescription || "");
const [price, setPrice] = useState(existingPrice || "");
const [images, setImages] = useState(existingImages || []);
const [goToProducts, setGoToProducts] = useState("");
const [isUploading, setIsUploading] = useState(false);
const router = useRouter();
async function saveProduct(ev) {
ev.preventDefault();
const data = { title, description, price, images };
if (_id) {
await axios.put("/api/products", { ...data, _id });
} else {
await axios.post("/api/products", data);
}
setGoToProducts(true);
}
if (goToProducts) {
router.push("/products");
}
async function uploadImages(ev) {
const files = ev.target?.files;
if (files?.length > 0) {
setIsUploading(true);
const data = new FormData();
for (const file of files) {
data.append("file", file);
}
const res = await axios.post("/api/upload", data);
for (let i = 0; i < res.data.path.length; i++) {
console.log(res.data.path[i]);
}
setImages((OldImages) => {
return [...OldImages, ...res.data.path];
});
setIsUploading(false);
}
}
function updateImagesOrder(images) {
setImages(images);
}
return (
<form onSubmit={saveProduct}>
<label>Nazwa Produkt</label>
<input
type="text"
placeholder="Nazwa Produktu"
value={title}
onChange={(ev) => setTitle(ev.target.value)}
/>
<label>Opis Produktu</label>
<textarea
placeholder="Opis"
value={description}
onChange={(ev) => setDescription(ev.target.value)}
></textarea>
<label>Zdjęcia Produktu</label>
<div className="mb-2 flex flex-wrap gap-1">
<ReactSortable
list={images}
className="flex flex-wrap gap-1"
setList={updateImagesOrder}
>
{images?.length &&
images.map((path) => (
<div key={path}>
<Image
src={path}
alt="product_image"
width={0}
height={0}
sizes="6rem"
style={{ width: "100%", height: "100px" }}
className="rounded-lg"
/>
</div>
))}
</ReactSortable>
{isUploading && (
<div className="h-24 flex items-center">
<Spinner />
</div>
)}
<label className="w-24 h-24 cursor-pointer text-center flex items-center justify-center text-sm gap-1 text-gray-500 rounded-lg bg-gray-200">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5m-13.5-9L12 3m0 0 4.5 4.5M12 3v13.5"
/>
</svg>
<div>Wgraj</div>
<input
type="file"
onChange={uploadImages}
className="hidden"
multiple
></input>
</label>
</div>
<label>Cena Produktu</label>
<input
type="number"
placeholder="Cena"
value={price}
onChange={(ev) => setPrice(ev.target.value)}
/>
<button type="submit" className="btn-primary">
Zapisz Produkt
</button>
</form>
);
}
Images work normal when function don't do anything:
function updateImagesOrder(images) {
console.log(images);
}
and in console display:
(2) [String, String] 0 : String {'/2024-02-07T15-43-47.272Z-Fundamental.png', chosen: false, selected: false} 1 : String {'/2024-02-07T15-43-47.260Z-css-flexbox-poster.png', chosen: false, selected: false} length : 2
But when I want implement react-sortablejs by changing:
function updateImagesOrder(images) {
setImages(images);
}
Images don't work and I have error in console:
Image is missing required "src" property:
How to use this react-sortablejs with local images?
react-sortablejs is somehow converting the urls.
I managed to fix by converting it back to regular strings using either:
or