Last active
October 12, 2024 15:41
-
-
Save Nachasic/0431415eec47b4bd090a65bade6e8597 to your computer and use it in GitHub Desktop.
Serialize react to JSON and de-serialize it back with TypeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
import { mount } from 'enzyme'; | |
import { serialize, deserialize } from './react-seritalize'; | |
class CustomComponent extends React.Component<any, any> { | |
render () { | |
return <div className="CustomComponent" >{this.props.children}</div> | |
} | |
} | |
const INJECTABLE_TAG = (props: any) => <span className="INJECTABLE_TAG">{props.children}</span>; | |
const MyAwesome = (props: { children: React.ReactNode }) => <span className="FunctionalComponent"></span>; | |
const testComponent = <div> | |
This is a test component with some <MyAwesome>inline stuff happening</MyAwesome> | |
<INJECTABLE_TAG> | |
Be prepared for awesomness!!! | |
</INJECTABLE_TAG> | |
</div> | |
describe('React serialization tests', () => { | |
it('should serialize components', () => { | |
const ser = serialize(testComponent); | |
const deser = deserialize(ser, { | |
components: { | |
[INJECTABLE_TAG.name]: CustomComponent, | |
[MyAwesome.name]: MyAwesome | |
} | |
}) | |
const wrapper = mount(deser) | |
console.log(wrapper.html()) | |
}) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* React-Serialize utility re-written in TypeScript | |
* Originally created by @pravdomil (https://github.com/pravdomil/react-serialize) | |
*/ | |
import * as React from 'react'; | |
type ObjectType = { | |
[index: string]: any; | |
} | |
type DeserializableComponent = { | |
type: string; | |
props: { children: DeserializableComponent[]; } & ObjectType | |
} | |
type ReviverOptions = { | |
type: string | React.ComponentType, | |
props: { children: DeserializableComponent[] & ObjectType }, | |
key: string | number, | |
components: { [type: string]: React.ComponentType } | |
} | |
type DeserializationOpts = { | |
components?: { [type: string]: React.ComponentType }; | |
reviver?: (args: ReviverOptions) => ReviverOptions | |
} | |
function deserializeElement(element: DeserializableComponent[] | DeserializableComponent | string | null, options: DeserializationOpts = {}, key?: string | number) { | |
let { components = {}, reviver } = options | |
if (typeof element !== "object") { | |
return element | |
} | |
if (element === null) { | |
return element | |
} | |
if (element instanceof Array) { | |
return element.map((el, i) => deserializeElement(el, options, i)) | |
} | |
let { props } = element; | |
const elementType = element.type; | |
if (typeof elementType !== "string") { | |
throw new Error("Deserialization error: element type must be string") | |
} | |
let type = components[elementType] || elementType.toLowerCase() | |
if (props.children) { | |
props = { ...props, children: deserializeElement(props.children, options) } | |
} | |
if (reviver) { | |
({ type, props, key, components } = reviver({ type, props, key, components })) | |
} | |
return React.createElement(type, { ...props, key }) | |
} | |
export const serialize = <T extends React.Component | JSX.Element>(component: T) => { | |
const getName = (value: string | Function) => { | |
if (typeof value === 'string') { | |
return value | |
} else if (typeof value === 'function') { | |
return value.name | |
} | |
return value | |
} | |
const replacer = (key: string, value: any) => { | |
switch (key) { | |
case "type": | |
return getName(value); | |
case "_owner": | |
case "_store": | |
case "ref": | |
case "key": | |
return | |
default: | |
return value | |
} | |
} | |
return JSON.stringify(component, replacer); | |
} | |
export const deserialize = <T extends React.ReactElement<any>>(serializedComponent: string, options?: DeserializationOpts): T => { | |
const componentData = JSON.parse(serializedComponent); | |
return deserializeElement(componentData, options) as T; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment