React Native JSON.stringify cannot serialize cyclical structures
Asked Answered
M

5

15

We're building a RN app (RN0.37), and we're running into an issue where when the app is run, we get a "TypeError: JSON.stringify cannot serialize cyclic structures".

Nothing of relevance has changed on the API responses, and the issues went away recently, but reappeared upon a wipe/rebuild (triggered by unrelated issues).

My suspicions are around a couple of packages being used: “react-native-router-flux” and "react-native-permissions”, but I haven't been able to find anything of relevance in the app.

Currently my suspicions around "react-native-router-flux" are mainly based around this article: https://github.com/aksonov/react-native-router-flux/issues/363

And my suspicions around "react-native-permissions" is mostly founded on the fact that the timing of the inclusion of this package on this project is suspicious, and seems to coincide with the surfacing of this error - although I can't prove that with absolute certainty.

The only additional clue I have, is that the JSON.stringify error always seems to be preceded by a list of warnings. They all read "This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See https://facebook.github.io/react/docs/events.html#event-pooling for more information." The list of goes as follows (always in the same order): nativeEvent, type, target, currentTarget, eventPhase, bubbles, cancelable, timeStamp, defaultPrevented, isTrusted and touchHistory.

The following is my package.json:

"dependencies": {
  "blueimp-md5": "2.5.0",
  "moment": "2.16.0",
  "phone-formatter": "0.0.2",
  "react": "15.3.2",
  "react-native": "0.37.0",
  "react-native-asset-library-to-base64": "1.0.1",
  "react-native-aws3": "0.0.3",
  "react-native-button": "1.7.1",
  "react-native-cached-image": "1.2.2",
  "react-native-camera-kit": "4.0.1",
  "react-native-camera-roll-picker": "1.1.9",
  "react-native-contacts": "0.5.2",
  "react-native-fbsdk": "0.4.0",
  "react-native-fetch-blob": "0.10.0",
  "react-native-fs": "2.0.1-rc.2",
  "react-native-geocoder": "0.4.5",
  "react-native-image-crop-picker": "0.10.5",
  "react-native-image-resizer": "0.0.12",
  "react-native-nav": "1.1.4",
  "react-native-permissions": "0.2.5",
  "react-native-photo-view": "1.2.0",
  "react-native-router-flux": "3.37.0",
  "react-native-stripe": "1.2.1",
  "react-native-swipe-list-view": "0.3.1",
  "react-redux": "4.4.6",
  "redux": "3.6.0",
  "redux-storage": "4.1.1",
  "redux-storage-engine-reactnativeasyncstorage": "1.0.2",
  "underscore": "1.8.3"
}
Mcintire answered 16/2, 2017 at 6:25 Comment(2)
Are you perhaps logging a cyclic object out to console, and serialising it first?Estellestella
We discovered that the issues has been there all along, and the reason for its intermittence had to do with the use of Javascript Debugging being enabled on the emulator. Still not sure what the issue is.Mcintire
D
12

Passing this getCircularReplacer function as a second parameter into JSON.stringify() will fix this error:

const getCircularReplacer = () => {
    const seen = new WeakSet();
    return (key, value) => {
    if (typeof value === "object" && value !== null) {
        if (seen.has(value)) {
            return;
        }
        seen.add(value);
    }
    return value;
    };
};

Then you can use it as follows:

JSON.stringify(circularReference, getCircularReplacer());
// {"otherData":123}
Driblet answered 22/8, 2019 at 18:21 Comment(2)
Why would you use a WeakSet here? Wont all the allocated memory for the set be cleared when the stringification is done?Lingle
JSON.stringify needs to know when to stop the strange loop. The allocated memory is not cleared until a duplicate is found.Driblet
E
5

JSON.stringify can not handle JSON objects that have a reference to itself or portions of itself.

Link

I've made a simple library for the lazy that overrides the JSON.stringify() to allow it to handle circular references without producing an exception. It keeps you from changing anything in 3rd party libraries concerning this limitation. Install this at the bootstrap of your code.

Link 2

Eglantine answered 25/6, 2017 at 7:31 Comment(0)
M
4

you're writing for REACT NATIVE but it seems you have used onChange on textInput instead of onChangeText which is a right method for React Native when you're interested with updated value of the text input,

Mortgagor answered 28/6, 2020 at 14:14 Comment(2)
onChange when used on REACT NATIVE will give back { nativeEvent: { eventCount, target, text} } thats why JSON.stringify() is complaining its cyclicMortgagor
Welcome mate, lets hack this :)Mortgagor
P
1

After spending half a day, I found this fantastic way, especially for React Naive, first of all, install json-stringify-safe, if you're working by using Typescript, install it too @types/json-stringify-safe.

Then I prepared these two utils functions:

import serialize from 'json-stringify-safe';

const stringify = (any: any): string => serialize(any);

const parsify = (serializedString: string): any => eval(`(${serializedString})`);
Paction answered 22/11, 2022 at 22:1 Comment(0)
S
-1

I was facing this issue on my React Native (0.73.1) app when trying to parse a cyclic reference. I updated my node version from 18 to 20.11.0. Then the error was gone.

Shemikashemite answered 23/3 at 4:8 Comment(1)
Doesn't even make any senseSingularity

© 2022 - 2024 — McMap. All rights reserved.