SolidJSS
SolidJSโ€ข2y agoโ€ข
6 replies
Basil

Nested Immer "produce" signals with components

I'm trying to implement something like this, which would allow me to create "nested" signals that update the upmost signal:

function createImmerSignal<T>(value: T) {
  const [get, set] = createSignal(value);

  function newSet(callback: (draft: Draft<T>) => void) {
    const newVal = produce(get(), callback, (redo, undo) => {
      // Undo and redo logic
    });
    // eslint-disable-next-line @typescript-eslint/ban-types
    set(newVal as Exclude<T, Function>);
  }

  return [get, newSet];
}

type Company = {
  name: string;
  developers: {
    name: string;
    someOtherProp: string;
  }[];
};

function CompOne(prop: { origCompany: Company }) {
  const [company, setCompany, createNested] = createImmerSignal<Company>(origCompany);

  // I'm not sure what a good syntax for this would be, or how to even get this functional. This syntax is what I've come up with:
  const dev = createNested(company => company.developers[0]);

  return <>
    <CompTwo dev={dev} />
  </>
}

function CompTwo(props) {
  // createNested can be used indefinitely
  const [dev, setDev, createNested] = props.dev;

  setDev(draft => {
    // This would update company.developers[0].someProp
    draft.name = 'aaaa';
  });

  return <></>;
}


I'm specifically trying to avoid having to use setCompany in a nested component, because that would become pretty unwieldy very quickly:

setCompany(draft => {
  draft.developers[0].someProp.anotherProp[2].enabled = true;
});


However, I'm not sure how to do this.
Was this page helpful?