UNPKG

7.71 kBMarkdownView Raw
1# @bearer/react
2
3[![Version](https://img.shields.io/npm/v/@bearer/react.svg)](https://npmjs.org/package/@bearer/react)
4![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/@bearer/react.svg)
5![node (scoped)](https://img.shields.io/node/v/@bearer/node.svg)
6[![Downloads/week](https://img.shields.io/npm/dw/@bearer/react.svg)](https://npmjs.org/package/@bearer/react)
7![NPM](https://img.shields.io/npm/l/@bearer/react)
8
9React tooling for bearer.sh components
10
11## Installation
12
13Install dependencies
14
15```bash
16yarn add @bearer/js @bearer/react
17```
18
19## Factory
20
21Factory lets you create components or HOC scoped for an integration. It prevents your to repeat yourself.
22We recommend creating a file per integration so that it is easier to maintain on the long run (totaly up to you of course)
23
24```tsx
25import { factory, Bearer } from '@bearer/react'
26const { Connect, withInvoke } = factory('my-integration-name')
27```
28
29### `Connect` component
30
31This component expect a `setupId` to authenticate the final user.
32
33```tsx
34import { factory } from '@bearer/react'
35const { Connect } = factory('my-integration-name')
36
37class MyComponent extends React.Component {
38 handleSuccess = ({ authId }) => {
39 // do whatever you want with the authId received
40 }
41 render() {
42 return (
43 <Bearer clientId="BEARER_PUBLISHABLE_KEY">
44 <Connect
45 setupId="setupId"
46 render={({ loading, connect, error }) => {
47 if (loading) {
48 return <Loading />
49 }
50 if (error) {
51 return (
52 <div>
53 Error, please retry <button onClick={() => connect()}>Retry</button>
54 </div>
55 )
56 }
57 return <button onClick={connect}>Connect ...</button>
58 }}
59 />
60 </Bearer>
61 )
62 }
63}
64```
65
66### `withInvoke` HOC
67
68If for any reasons you want to display data coming bearer but without using built in Web Components, you can easily connect your React application with Bearer servers. More on React HOCs [here](https://reactjs.org/docs/higher-order-components.html)
69
70Assuming we have a backend function named `GimmeData` returning an array of string
71
72```tsx
73// myConnectedToBearerComponent.tsx
74import { factory } from '@bearer/react'
75const { withInvoke } = factory('my-integration-name')
76
77interface TProps {
78 loading: boolean
79 error?: any
80 data?: { title: string }
81 invoke: (params: any) => void
82 otherDataYouWantToPass: string
83}
84
85function DisplayComponent(props: TProps) {
86 if (props.loading) {
87 return 'Loading'
88 }
89 if (props.error) {
90 return <div>Error: {props.error}</div>
91 }
92 if (props.data) {
93 return <div>Some data passed: {props.data}</div>
94 }
95
96 const invoke = () => {
97 props.invoke({ query: { authId: 'AUTH_ID' } })
98 }
99
100 return (
101 <div>
102 {props.otherDataYouWantToPass}
103 <button onClick={invoke}>Click to invoke</button>
104 </div>
105 )
106}
107
108export default withInvoke('GimmeData')(DisplayComponent)
109// if you want to add typing
110//export default withInvoke<string[], { otherDataYouWantToPass: string }>('GimmeData')(DisplayComponent)
111```
112
113## fromBearer
114
115This component takes html tag name of a component as well as optional type information to produce a react component that can we re-used throughout an application.
116
117```tsx
118import * as React from 'react'
119const MyText = fromBearer<{ text?: string; anotherPropery: string }>('bearer-my-text')
120
121class ReactComponent extends React.Component {
122 render() {
123 return <MyText text="hello" anotherPropery="world" />
124 }
125}
126```
127
128Output events can be handled by simply adding the eventname as a prop on the component and adding a basic handler
129
130```tsx
131<Share bearer-uuid-feature-shared={this.onShared} />
132```
133
134For these tags to work correctly they must have a parent `Bearer`
135
136## Bearer
137
138This component maintains a shared state for a group of components as well as adding the bearer script tags to the page. This tag can be added at any level of the application as is convenient for the implementation
139
140### Example Use
141
142we will use [this integration](https://app.bearer.sh/integrations/6d29c4-share-slack-beta-4/preview) for our examples:
143
144First on the preview page obtain a setup-id from the setup components so we do not need to include these in our page. Next lets define our components in a constants file:
145
146`bearer.ts`
147
148```TS
149import { fromBearer } from '@bearer/react'
150
151export const ChannelSelect = fromBearer('bearer-6d29c4-share-slack-beta-4-channel-action')
152export const Share = fromBearer<{message?:string, text?:string}>('bearer-6d29c4-share-slack-beta-4-feature-action')
153export const SlackConnect = fromBearer('bearer-6d29c4-share-slack-beta-4-connect-action')
154```
155
156We can include the `Bearer` at any level but in this example lets use it all together in the same component
157
158`slack-share-component.tsx`
159
160```tsx
161import * as React from 'react'
162import { Bearer } from '@bearer/react'
163import { SlackConnect, ChannelSelect, Share } from '../../constants/bearer'
164
165export default class SlackShareSetup extends React.Component {
166 public render() {
167 const intialContext = { 'setup-id': 'SETUP_ID_SAMPLE' }
168 return (
169 <Bearer clientId="BEARER_PUBLISHABLE_KEY" initialContext={intialContext}>
170 <SlackConnect />
171 <ChannelSelect />
172 <Share message="hello world!" text="Test!" bearer-6d29c4-share-slack-beta-4-feature-shared={this.onShared} />
173 </Bearer>
174 )
175 }
176}
177```
178
179This allows to share messages but what if we want to persist the users setup information. @bearer/react provides two methods to acomplish this.
180
181### Using onUpdate
182
183`Bearer` has an `onUpdate`callback we can hook into which is called every time data changes within the provider
184
185`slack-share-component.tsx`
186
187```tsx
188import * as React from 'react'
189import { Bearer } from '@bearer/react'
190import { SlackConnect, ChannelSelect, Share } from '../../constants/bearer'
191
192export default class SlackShareSetup extends React.Component {
193 public render() {
194 const intialContext = { 'setup-id': 'SETUP_ID_SAMPLE' }
195 return (
196 <Bearer
197 clientId="BEARER_PUBLISHABLE_KEY"
198 initialContext={intialContext}
199 onUpdate={(data: any) => {
200 this.setState({ data })
201 }}
202 >
203 <SlackConnect />
204 <ChannelSelect />
205 <Share message="hello world!" text="Test!" bearer-6d29c4-share-slack-beta-4-feature-shared={this.onShared} />
206 <button onClick={this.handleSave}>Save Setup</button>
207 </Bearer>
208 )
209 }
210 private handleSave = () => console.log('handleSave', this.state.data)
211}
212```
213
214### using a context consumer
215
216Internally `Bearer` uses the [react context API](https://reactjs.org/docs/context.html). For a more advaned but flexable method we can access the consumer directly via `BearerContext` and then use the currently set details as we wish.
217
218`slack-share-component.tsx`
219
220```tsx
221import * as React from 'react'
222import { Bearer, BearerContext } from '@bearer/react'
223import { SlackConnect, ChannelSelect, Share } from '../../constants/bearer'
224
225export default class SlackShareSetup extends React.Component {
226 public render() {
227 const intialContext = { 'setup-id': 'SETUP_ID_SAMPLE' }
228 return (
229 <Bearer clientId="BEARER_PUBLISHABLE_KEY" initialContext={intialContext}>
230 <SlackConnect />
231 <ChannelSelect />
232 <Share message="hello world!" text="Test!" bearer-6d29c4-share-slack-beta-4-feature-shared={this.onShared} />
233 <BearerContext.Consumer>
234 {context => <button onClick={this.handleSave(context.state)}>Save Setup</button>}
235 </BearerContext.Consumer>
236 </Bearer>
237 )
238 }
239 private handleSave = (data: any) => () => {
240 console.log('handleSave', data)
241 }
242}
243```