|
1 | 1 | # React
|
2 |
| -We provide a higher-order component to connect to enhance presentational components to react to any observable (not limited to those generated by **Subspace**). |
| 2 | +Subspace also provides a set of components that simplifies its usage within React projects through the `@embarklabs/subspace-react` package. |
| 3 | + |
| 4 | +### Install |
| 5 | +You can install it through npm or yarn: |
| 6 | +``` |
| 7 | +npm install --save @embarklabs/subspace-react web3 rxjs # RxJS and Web3.js are needed peer-dependencies |
| 8 | +``` |
3 | 9 |
|
4 | 10 | ### Usage
|
5 |
| -```js |
6 |
| -import { observe } from '@embarklabs/subspace/react'; |
7 | 11 |
|
8 |
| -const ObserverComponent = observe(WrappedComponent); |
9 |
| -``` |
| 12 | +#### SubspaceProvider |
| 13 | +To use most of the `subspace-react` components, you need to wrap your app with the `<SubspaceProvider web3={web3} />` component. This will make Subspace available to any nested components that accesses it via the `useSubspace` hook or has been wrapped in the `withSubspace` higher order component. Any React component might use Subspace so it makes sense to add the provider near the top level of your dApp. The `SubspaceProvider` requires a web3 object |
10 | 14 |
|
11 |
| -This enhanced component will subscribe to any observable property it receives when the component is mounted and automatically unsubscribe when the component is unmounted. |
| 15 | +```js |
| 16 | +// index.js |
| 17 | +import React from 'react' |
| 18 | +import ReactDOM from 'react-dom' |
| 19 | +import MyApp from './MyApp' |
| 20 | +import { SubspaceProvider } from '@embarklabs/subspace-react'; |
12 | 21 |
|
13 |
| -### Example |
| 22 | +const web3 = new Web3("ws://localhost:8545"); |
14 | 23 |
|
15 |
| -::: tip |
16 |
| -This example is available in [Github](https://github.com/embark-framework/subspace/tree/master/examples/react-example1) |
17 |
| -::: |
| 24 | +const rootElement = document.getElementById('root') |
| 25 | +ReactDOM.render( |
| 26 | + <SubspaceProvider web3={web3}> |
| 27 | + <MyApp /> |
| 28 | + </SubspaceProvider>, |
| 29 | + rootElement |
| 30 | +); |
| 31 | +``` |
18 | 32 |
|
19 | 33 |
|
20 |
| -#### MyComponentObserver.js |
| 34 | +#### useSubspace |
| 35 | +Rather than relying on global variables or passing Subspace through props, The easiest way to access Subspace features is via the `useSubspace` hook. Be sure that your entire dApp is wrapped with a `<SubspaceProvider />` to have it available througout the component tree. |
21 | 36 | ```js
|
22 |
| -import React from "react"; |
23 |
| -import ReactDOM from 'react-dom'; |
24 |
| -import {observe} from "@embarklabs/subspace/react"; |
| 37 | +// index.js |
| 38 | +import React from 'react' |
| 39 | +import { useSubspace } from '@embarklabs/subspace-react'; |
25 | 40 |
|
26 |
| -const MyComponent = ({eventData}) => { |
27 |
| - // Handle initial state when no data is available |
28 |
| - if (!eventData) { |
29 |
| - return <p>No data</p>; |
30 |
| - } |
31 |
| - |
32 |
| - return <p>{eventData.someReturnedValue}</p> |
33 |
| -}; |
| 41 | +const MyComponent = () => { |
| 42 | + const subspace = useSubspace(); |
34 | 43 |
|
35 |
| -// MyComponent will now observe any observable prop it receives |
36 |
| -// and update its state whenever the observable emits an event |
37 |
| -export default observe(MyComponent); |
38 |
| -``` |
| 44 | + // do something.... |
| 45 | + // subspace.trackBalance(web3.eth.defaultAccount); |
39 | 46 |
|
40 |
| -#### App.js |
41 |
| -```js |
42 |
| -import React, {Component} from 'react'; |
43 |
| -import ReactDOM from 'react-dom'; |
44 |
| -import Subspace from '@embarklabs/subspace'; |
| 47 | + return ...; |
| 48 | +} |
45 | 49 |
|
46 |
| -import MyComponentObserver from './MyComponentObserver'; |
| 50 | +export default MyComponent |
| 51 | +``` |
47 | 52 |
|
48 |
| -class App extends Component { |
49 |
| - state = { |
50 |
| - myEventObservable$: null |
51 |
| - } |
52 | 53 |
|
53 |
| - async componentDidMount() { |
54 |
| - const MyContractInstance = ...; // TODO: obtain a web3.eth.contract instance |
| 54 | +#### withSubspace |
| 55 | +This higher order component is provided as an alternative to the `useSubspace` hook. This injects the `subspace` property with an already initialized Subspace instance. Just like with the hook, your entire dApp needs to be wrapped with a `<SubspaceProvider />`. |
55 | 56 |
|
56 |
| - const subspace = new Subspace("wss://localhost:8545"); // Use a valid provider (geth, parity, infura...) |
57 |
| - await subspace.init() |
58 |
| - |
59 |
| - const myEventObservable$ = subspace.trackEvent(MyContractInstance, "MyEvent", {filter: {}, fromBlock: 1 }); |
60 |
| - this.setState({ myEventObservable$ }); |
61 |
| - } |
| 57 | +```js |
| 58 | +// index.js |
| 59 | +import React from 'react' |
| 60 | +import { withSubspace } from '@embarklabs/subspace-react'; |
62 | 61 |
|
63 |
| - render() { |
64 |
| - return <MyComponentObserver eventData={this.state.myEventObservable$} />; |
65 |
| - } |
| 62 | +const MyComponent = (props) => { |
| 63 | + // do something.... |
| 64 | + // props.subspace.trackBalance(web3.eth.defaultAccount); |
| 65 | + |
| 66 | + return ...; |
66 | 67 | }
|
67 | 68 |
|
68 |
| -export default App; |
| 69 | +export default withSubspace(MyComponent); |
69 | 70 | ```
|
70 | 71 |
|
71 |
| -::: warning Handling Contract Objects |
72 |
| -The variable `MyContractInstance` is a `web3.eth.Contract` object pointing to a deployed contract address. You can use a DApp framework like [Embark](https://embark.status.im/docs/contracts_javascript.html) to easily import that contract instance: `import { MyContract } from './embarkArtifacts/contracts';`, or use web3.js directly (just like in the example [source code](https://github.com/embarklabs/subspace/blob/master/examples/react/src/MyContract.js#L36-L42)) |
73 |
| -::: |
74 | 72 |
|
75 |
| -#### index.js |
| 73 | +#### observe |
| 74 | + |
| 75 | +Useful to make your component subscribe to any observable props it receives when the component is mounted and automatically unsubscribes when the component is unmounted. It can be used with any kind of observables. |
| 76 | + |
| 77 | + |
76 | 78 | ```js
|
77 |
| -import React from 'react'; |
78 |
| -import ReactDOM from 'react-dom'; |
79 |
| -import App from './App'; |
| 79 | +import { observe } from '@embarklabs/subspace-react'; |
80 | 80 |
|
81 |
| -ReactDOM.render(<App />, document.getElementById('root')); |
| 81 | +const ObserverComponent = observe(WrappedComponent); |
82 | 82 | ```
|
83 | 83 |
|
84 |
| - |
| 84 | +##### Example usage: |
85 | 85 | ```js
|
86 |
| -import { observe } from "@embarklabs/subspace/react"; |
87 |
| - |
88 |
| -const ProductComponent = ({ maxRating, minRating, averageRating }) => { |
89 |
| - return <ul> |
90 |
| - <li><b>minimum rating: </b> {minRating}</li> |
91 |
| - <li><b>maximum rating: </b> {maxRating}</li> |
92 |
| - <li><b>average rating: </b> {averageRating}</li> |
93 |
| - </ul>; |
| 86 | +const MyComponent = ({eventData}) => { |
| 87 | + // Handle initial state when no data is available |
| 88 | + if (!eventData) { |
| 89 | + return <p>No data</p>; |
| 90 | + } |
| 91 | + |
| 92 | + return <p>Value: {eventData.someReturnValue}</p> |
94 | 93 | };
|
95 | 94 |
|
96 |
| -const ReactiveProductComponent = observe(ProductComponent); |
97 | 95 |
|
98 |
| -const Product = subspace.contract({abi, address}); |
99 |
| -const rating$ = Product.events.Rating.track().map("rating").pipe(map(x => parseInt(x))); |
| 96 | +const MyEnhancedComponent = observe(MyComponent); |
100 | 97 |
|
101 |
| -ReactDOM.render( |
102 |
| - <ReactiveProductComponent |
103 |
| - maxRating={rating$.pipe($max())} |
104 |
| - minRating={rating$.pipe($min())} |
105 |
| - averageRating={rating$.pipe($average())} |
106 |
| - />, |
107 |
| - document.getElementById('hello-example') |
108 |
| -); |
| 98 | + |
| 99 | +const SomeOtherComponent = () => { |
| 100 | + const myObservable$ = MyContractInstance.events.MyEvent.track({fromBlock: 1}); |
| 101 | + return <MyEnhancedComponent myProp={myObservable$} />; |
| 102 | +} |
109 | 103 | ```
|
| 104 | + |
| 105 | +::: warning Handling Contract Objects |
| 106 | +The variable `MyContractInstance` is a `web3.eth.Contract` object pointing to a deployed contract address that has been enhanced with `subspace.contract()`. You can use a DApp framework like [Embark](https://embark.status.im/docs/contracts_javascript.html) to easily import that contract instance: `import { MyContract } from './embarkArtifacts/contracts';`. |
| 107 | +::: |
| 108 | + |
| 109 | +::: tip |
| 110 | +To learn more about how to use `subspace-react`, there are full working examples available in [Github](https://github.com/embark-framework/subspace/tree/master/examples/) |
| 111 | +::: |
0 commit comments