Created
September 9, 2017 00:00
-
-
Save adambard/fadb2e0ca06054ab899fe0d54b8f5bbf to your computer and use it in GitHub Desktop.
React GRPC HOC
This file contains hidden or 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 jspb from 'google-protobuf' | |
import { Code, grpc } from 'grpc-web-client' | |
import React from 'react' | |
export interface RPCResponseData<TResult, TOwnProps> { | |
ownProps: TOwnProps | |
loading: boolean | |
result: TResult | null | |
status: Code | null | |
statusMessage: string | |
} | |
export type RPCPropertyMapper<TOwnProps, TResult, TResultProps> = | |
(data: RPCResponseData<TResult, TOwnProps>) => TResultProps | |
interface RPCProviderState<TResultProps> { | |
result: TResultProps | null | |
} | |
type Component<TProps> = | |
React.StatelessComponent<TProps> | |
| React.ComponentClass<TProps> | |
interface MapRPCOptions<TOwnProps, TRequest extends jspb.Message, TResult extends jspb.Message, TResultProps> { | |
method: grpc.UnaryMethodDefinition<TRequest, TResult>, | |
host: string, | |
request: TRequest | ((props: TOwnProps) => TRequest), | |
props: RPCPropertyMapper<TOwnProps, TResult, TResultProps> | |
} | |
export function wrapRPCProvider<TOwnProps extends object, | |
TRequest extends jspb.Message, | |
TResult extends jspb.Message, | |
TResultProps extends object>( | |
options: MapRPCOptions<TOwnProps, TRequest, TResult, TResultProps> | |
) { | |
return (Comp: Component<TOwnProps & TResultProps>) => { | |
type State = RPCProviderState<TResultProps> | |
return class RPCProvider extends React.Component<TOwnProps, State> { | |
static displayName = `RPCProvider(${Comp.displayName || Comp.name})` | |
componentWillMount() { | |
this.setState({ | |
result: options.props({ | |
loading: true, | |
ownProps: this.props, | |
result: null, | |
status: null, | |
statusMessage: '' | |
}) | |
}) | |
grpc.unary(options.method, { | |
host: options.host, | |
request: (options.request instanceof Function) ? options.request(this.props) : options.request, | |
onEnd: ({status, message, statusMessage}: grpc.UnaryOutput<TResult>) => { | |
this.setState({ | |
result: options.props({ | |
loading: false, | |
result: message, | |
ownProps: this.props, | |
status, | |
statusMessage | |
}) | |
}) | |
} | |
}) | |
} | |
render() { | |
const {result} = this.state | |
const props = Object.assign({}, this.props, result) | |
return <Comp {...props}/> | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment