最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Node.js: How to serializedeserialize a React component? - Stack Overflow

programmeradmin4浏览0评论

I would like to serialize a React element (an instance of React component given props) and deserialize it elsewhere. Why you ask? I would like to be able to send the class from one process over stdout and render it in another process. I also want the rendered component to be interactive, so simply using ReactDOM.renderToString() will not suffice...

What I've tried:

  • Serializing it as a string and using eval() to deserialize it
  • Using a custom replacer and reviver functions for JSON.stringify() and JSON.parse() respectively

MyReactComponent.toString() returns:

"function MyReactClass() {
    _classCallCheck(this, MyReactClass);

    _get(Object.getPrototypeOf(MyReactClass.prototype), 'constructor', this).apply(this, arguments);
}"

which doesn't contain any of the methods unique to my component (such as render() or constructor()).

See this example code in JS Bin: ,console,output

I would like to serialize a React element (an instance of React component given props) and deserialize it elsewhere. Why you ask? I would like to be able to send the class from one process over stdout and render it in another process. I also want the rendered component to be interactive, so simply using ReactDOM.renderToString() will not suffice...

What I've tried:

  • Serializing it as a string and using eval() to deserialize it
  • Using a custom replacer and reviver functions for JSON.stringify() and JSON.parse() respectively

MyReactComponent.toString() returns:

"function MyReactClass() {
    _classCallCheck(this, MyReactClass);

    _get(Object.getPrototypeOf(MyReactClass.prototype), 'constructor', this).apply(this, arguments);
}"

which doesn't contain any of the methods unique to my component (such as render() or constructor()).

See this example code in JS Bin: http://jsbin.com/febuzupicu/edit?js,console,output

Share Improve this question edited Jan 29, 2016 at 22:02 senornestor asked Jan 29, 2016 at 20:50 senornestorsenornestor 4,1652 gold badges35 silver badges33 bronze badges 5
  • Not sure what you mean RE renderToString - it would still be interactive once rendered and inited on the client. You don't need to worry about serializing the react component if you have your state in a store (e.g. redux) - you would only need to serialize the store. Of course any state just in the component instance would be lost, but you could write pure components – nanobar Commented Jan 29, 2016 at 20:55
  • The problem is that the React component class does not exist at the destination, so I would not be able to call ReactDOM.render() at the destination. I'm trying to figure out how I can access the React component class from the destination, whether that be sending it as a string from the origin (which hasn't worked yet), saving it to a file and requiring that file from the destination (since both processes will be running on the same machine), etc. – senornestor Commented Jan 29, 2016 at 21:40
  • Can you not just send the entire file, load it and use eval on it on the receiving end? – Henrik Andersson Commented Jan 29, 2016 at 22:34
  • Can you provide a specific use case? One typically does not share an instance of a component between clients, only the data required to create a new instance elsewhere. – Rob Raisch Commented Jan 29, 2016 at 22:37
  • I'm building an Atom plugin that will allow a developer to write code and visualize the results. I want to allow for ad-hoc visualizations, so visualization code will be written developer-side and rendered plugin-side. All communication is happening console.log -> stdout, so it's strings. I thought it would be nice to serialize the viz code to a string and deserialize (eval) it and use it to render interactive visualizations. – senornestor Commented Jan 30, 2016 at 5:53
Add a comment  | 

3 Answers 3

Reset to default 5

Take a look at react-serialize. This package allows you to serialize react components into JSON strings and back.

I've looked around extensively, haven't found anything.

I'm currently writing my own hydrate/dehydrate that converts react components into arrays of arguments to be passed in recursively to React.createElement(). I think that's the only way of doing it reliably. I'll probably make a small library for it.

In theory, perhaps one could use React.renderToString(), and pass around the string? But then you'd be using dangerouslySetInnerHtml... :\

Another update:

Here's the library: https://github.com/finetype/react-serialize

It has limitations, and it isn't the prettiest code I've ever written, but it also has decent test coverage. It was quite a bit harder to write than I expected, and in the end I sacrificed some much-desired functionality to just get something consistent. Hopefully those will be improved over time, and pull requests are welcome.

But it works. :)

Edit: After going way down this route (actually added a ton of functionality to that code that I didn't add to the repo because I didn't add sufficient test coverage), we ended up deciding it was a rabbit hole of a problem that should only be used for fairly simple use cases, and that our use case introduced enough complexity that it became too much to be worth the cognitive load it added to the code. I'd caution someone from going down this route.

To answer my own question:

// If I stringify this
JSON.stringify({
  type: `React.createClass({
    render: function() {
      return <span>{this.props.name}</span>
    }
  })`,
  props: {
    name: 'Jorge'
  }
})

// Then I am able to parse it and deserialize it into a React element
let {type, props} = payload
// In Node
React.createElement(vm.runInNewContext(type, {React}), props)
// Not in Node
React.createElement(eval(type), props)
发布评论

评论列表(0)

  1. 暂无评论