How do I use Solid.js with clear data model <-> UI primitive distinction?

Suppose I have a ES6 Map object like following:
const initialFiles = new Map([
["a.txt", "foo"],
["b.txt", "bar"],
["c.txt", "baz"],
])
const initialFiles = new Map([
["a.txt", "foo"],
["b.txt", "bar"],
["c.txt", "baz"],
])
Then using Solid.JS, I want to create an user interface to modify this object.
function App() {
  const [files, setFiles] = createSignal(initialFiles);

  const handleFileChange = (fileName: string, value: string) => {
    const newFiles = new Map(files());
    newFiles.set(fileName, value);
    setFiles(newFiles);
  };

  return (
    <div>
      <FileEditor
        value={files().get("a.txt") ?? ""}
        onChange={(value) => handleFileChange("a.txt", value)}
      />

      <FileEditor
        value={files().get("b.txt") ?? ""}
        onChange={(value) => handleFileChange("b.txt", value)}
      />

      <FileEditor
        value={files().get("b.txt") ?? ""}
        onChange={(value) => handleFileChange("a.txt", value)}
      />
    </div>
  );
}
function App() {
  const [files, setFiles] = createSignal(initialFiles);

  const handleFileChange = (fileName: string, value: string) => {
    const newFiles = new Map(files());
    newFiles.set(fileName, value);
    setFiles(newFiles);
  };

  return (
    <div>
      <FileEditor
        value={files().get("a.txt") ?? ""}
        onChange={(value) => handleFileChange("a.txt", value)}
      />

      <FileEditor
        value={files().get("b.txt") ?? ""}
        onChange={(value) => handleFileChange("b.txt", value)}
      />

      <FileEditor
        value={files().get("b.txt") ?? ""}
        onChange={(value) => handleFileChange("a.txt", value)}
      />
    </div>
  );
}
But the problem with this is that editing a single file causes the re-render of the entire App. The solution I have found is using ReactiveMap (https://www.npmjs.com/package/@solid-primitives/map), which is a reactive variant of ES6 Map. It works fine. However I feel like I am altering the data model only because of the choice of UI library. I will be passing files object to other functions which are irrelevant to Solid.JS, and they have to know what ReactiveMap is. Seems like a sign of bad abstraction. What would be a nicer way to handle this without losing fine-grained reactivity? Thank you 🙂
4 Replies
Brendonovich
Brendonovich10mo ago
If you want fine grained reactivity, you need to use stuff that hooks into solid's reactivity. I think the solid-independent solution to this would be to have the files be stored as a Map, but then have them be replicated into a reactive store whenever modified, like is done in a lot of the Tanstack solid packages. IMO you should just keep using ReactiveMap, seeing as you're specifically building a UI thing for solid
thetarnav
thetarnav10mo ago
However I feel like I am altering the data model only because of the choice of UI library.
Solid is designed to by default require exactly that, to use signals and reconcile in your data to be able to use object references as ids. You can also try to go the vue/svelte route and reconcile in the template, using Key instead of For for lists, and ids for equality checks.
Alex Lohr
Alex Lohr10mo ago
As an aside, have you seen my file system primitive? https://solid-primitives.netlify.app/package/filesystem - it might be helpful for you.
Solid Primitives
A library of high-quality primitives that extend SolidJS reactivity
서동휘
서동휘OP10mo ago
Thank you all for answers! filesystem primitive also looks very applicable to my project. Thank you much 🙏
Want results from more Discord servers?
Add your server