14
votes

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"
}
3
Are you perhaps logging a cyclic object out to console, and serialising it first? - G0dsquad
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. - Vicente Opaso

3 Answers

10
votes

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}
5
votes

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

1
votes

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,