0

I'd like to update a react state (the "app" variable) object dynamically. The state has several properties, one of them is a nested object ("app.error" object). There is a kind of setter function ("setAppData") which takes any number of [existing key]: new value pairs of the state as parameter, create a new object and it should update the state according to "temp" object.

It works as intended when I want to update "app.error" using hard-coded variable or any other "app" properties, when I try to update the "app.error" using my setter function, it does not update.

const initialAppData: IAppData = {
  error: {} as IFrontEndError,
  interfaceTheme: UI_THEME.LIGHT,
};

function AppProvider(props: any) {
  const [app, setApp] = useState<IAppData>(initialAppData);

  useMemo(() => {
    window.addEventListener("error", (event) => {
      errorHandler({
        colno: event.colno,
        filename: event.filename,
        lineno: event.lineno,
        message: event.message,
      });
    });
  }, []);

  const errorHandler = (event: IFrontEndError) => setAppData({error: { ...event }});

  const setAppData = (newValue: TUpdateAppData) => {
    let key: keyof IAppData;
    let temp = getAppData();

    for (key in newValue) {
      if (
        !Object.prototype.hasOwnProperty.call(app, key) ||
        !Object.prototype.hasOwnProperty.call(newValue, key)
      )
        continue;
      temp = {
        ...temp,
        [key]: newValue[key],
      };
    }
    setApp({ ...temp, error: { ...temp.error } });
  };

  const getAppData = () => ({ ...app });

}

Using static update (it works as intended):

const setAppData = () => {
    let temp = getAppData();

    temp.error = {
      colno: 1,
      lineno: 1,
      message: "asd",
      filename: "asd"
    }

    setApp({ ...temp, error: { ...temp.error } });
  };

The structure of the "temp" objects before passing the spreaded copy to the state setter are exactly the same. "temp" object before spreading, triggered by event:

{
  "error": {
    "colno": 11,
    "filename": "http://127.0.0.1:5173/src/components/Debug.tsx?t=1667134926865",
    "lineno": 29,
    "message": "Error: asd"
  },
  "interfaceTheme": "light-theme"
}

getAppData() after error event:

{
  "error": {},
  "interfaceTheme": "light-theme"
}

"temp" object before spreading using hard-coded value:

{
  "error": {
    "colno": 1,
    "lineno": 1,
    "message": "asd",
    "filename": "asd"
  },
  "interfaceTheme": "light-theme"
}

getAppData() after execution using hard-coded value:

{
  "error": {
    "colno": 1,
    "lineno": 1,
    "message": "asd",
    "filename": "asd"
  },
  "interfaceTheme": "light-theme"
}

What is that I don't notice?

edit: sources of the project: https://github.com/gazsop/magus_shared https://github.com/gazsop/magus_react

Peter
  • 13
  • 4
  • You're reinventing the immer library – possum Oct 30 '22 at 15:24
  • I'm learning both react and typescript, there are unique/bad/unnecessary solutions in my codes but that is not the point, I'd like to understand as much as possible through lines like these. – Peter Oct 30 '22 at 15:51
  • I implemented everything you described in React 18.2, except I used JS instead of TS. Your code worked perfectly for me. When I ran getAppData() after generating an error event, all properties of the nested error object were correctly populated. – crosen9999 Oct 31 '22 at 20:17
  • @crosen9999 I use the same version of react with Vite 3.1. I've been trying to debug these 20 lines for days, I've done multiple different solutions, reinstall/update npm libraries, reading forums, articles. Can other hook causes this behavior? If other hooks prevent the nested state to be given properly, why is it work when I use hardcoded values? Did I set something in Vite/typescript/react config? I simplified it as much as possible to narrow the possible error sources down but I still don't understand why it does not work. – Peter Nov 01 '22 at 12:36
  • I edited the question, there are the 2 repos of the project at the end. It's a bit chaotic yet but I think it's readable. – Peter Nov 01 '22 at 13:30

0 Answers0