Search code examples
reactjsreduxredux-toolkitvitejss

Update JSS sheet on specific redux state subtree change


I am injecting JSS into a manually loaded iframe, and then launching a reload whenever certain values in my redux state change, as follows:

export default function ETFStyleUpdater({ sheet, id }: Props) {
  const readerConfig = useAppSelector((state) => state.bookReader[id] || DEFAULT_BOOK_READER_CONFIG_STATE);

  useEffect(() => {
    sheet.update(readerConfig);
  }, [readerConfig]);

  return <></>;
}

The react code is loaded as follows:

  const container = document.body.appendChild(document.createElement("div"));
  createRoot(container!).render(
    <Provider store={store}>
      <ETFStyleUpdater sheet={sheet} id={bookId} />
    </Provider>,
  );

While this felt nasty even when I wrote it, it worked fine with webpack. I am now moving to vitejs, which complains with a

Uncaught Error: @vitejs/plugin-react can't detect preamble. Something is wrong.

This all gets loaded dynamically into an iframe but by accessing the store via a property on window.parent, it worked just fine with webpack.

How can I get the same effect without creating a new react root and doing a nasty hack with useEffect? I tried to put a reference to the sheet onto window and use a redux-toolkit extraReducer (or middleware) but it doesn't seem to update, even though there is a reference there.


Solution

  • redux-watch seems to do the trick.

    let w = watch(store.getState, "bookReader");
    store.subscribe(
      w((newVal) => {
        sheet.update(newVal[bookId]);
      }),
    );