reactjs / server-components-demo

Demo app of React Server Components.
https://reactjs.org/server-components
MIT License
4.27k stars 639 forks source link

fix: JSON.parse fails in react-fetch #55

Open rgbkids opened 2 years ago

rgbkids commented 2 years ago

From: https://github.com/reactjs/server-components-demo/pull/50

gaearon commented 11 hours ago why is the data empty?

gaearon commented 6 hours ago i'll close because it's not supposed to be empty. if there's some case where it's empty let's figure out why.


About empty data: We are testing the RSC demo as a team.

I got a SyntaxError when testing with two people. The operation is as follows.

User
Operation 1 (User-A): User-A show the initial page. 01_Operator-A_01
Operation 2 (User-B): User-B show the initial page. 02_Operator-B_01
Operation 3 (User-B): User-B delete the first record. 03_Operator-B_02
Operation 4 (User-B): User-B finished deleting the first record. 04_Operator-B_03
Operation 5 (User-A): The first record is still visible on the screen of User-A. 05_Operator_A_02
Operation 6 (User-A): An error occurs when User-A taps the first record. 06_Operator_A_03

The logs are as follows.

Application Error
SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at Response.json (/opt/notes-app/node_modules/react-fetch/cjs/react-fetch.node.development.js:133:21)
    at Note (/opt/notes-app/src/Note.server.js:65:60)
    ...

When I looked into it, I found the cause of the error in react-fetch.

  json: function () {
    if (this._json !== null) {
      return this._json;
    }

    var buffer = readRecordValue(this._bufferRecord);
    var json = JSON.parse(buffer.toString());
    this._json = json;
    return json;
  },

Passing an empty character to JSON.parse will cause a SyntaxError.

let json1 = JSON.parse(""); // => SyntaxError
let json2 = JSON.parse([]); // => SyntaxError
let json3 = JSON.parse(null); // OK
let json4 = JSON.parse("null"); // OK

The problem is that the caller of react-fetch cannot catch SyntaxError. The application will go down before I can catch it.

For example:

  try {
    let result = fetch(`http://localhost:4000/notes/${selectedId}`);
    console.log(result);  // => ERROR:  invalid input syntax for type integer: "null"  STATEMENT:  select * from notes where id = $1
  } catch (error) {
    // SyntaxError is not caught.
    console.log(error);
  }

So we proposed a change in api.server.js.

res.json(rows[0]);

Just escape it like this

res.json(rows[0] || null);

This way, the caller of react-fetch can make the decision. Note.server.js does not need to be changed.