UNPKG

9.51 kBMarkdownView Raw
1# React Data Object Connect
2
3Utilities to connect AppframeWeb data objects to React components. Higher order components for class components, and hooks for function components.
4
5## Getting Started
6
7### Installation
8
9Install using npm
10
11```sh
12npm install @olenbetong/react-data-object-connect
13```
14
15or include the IIFE build in a script
16
17```html
18<script src="https://unpkg.com/@olenbetong/react-data-object-connect@4.0.0/dist/iife/index.min.js"></script>
19```
20
21### Hooks or connect/connectRow?
22
23This package provides 2 primary ways of connecting React components to Appframe data objects: the connect/connectRow HoC components, and hooks. `connect`/`connectRow` provide most of the state from the data objects, while with hooks you might need to use several hooks to get the information you need.
24
25Not sure if you should use the connect/connectRow functions, or the hooks? If you are using a React version > 16.8, it is recommended to only use the hooks, as they are more flexible, and usually result in smaller bundles.
26
27## Hooks
28
29If using a React with hooks, there are also data object hooks available.
30
31- **useCurrentIndex**(dataObject) - Returns only the current index
32- **useCurrentRow**(dataObject) - Returns the current record
33- **useData**(dataObject) - Returns an array with all records currently in the data object
34- **useDataWithFilter**(dataObject, filter, type) - Like useData, but loads data with the given filter. Type can be filterString or whereClause (defaults to filterString) and must be a string
35- **useDirty**(dataObject) - Returns a boolean indicating if the current row is dirty or not
36- **useError**(dataObject) - Returns any loading error message
37- **useLoading**(dataObject) - Returns a boolean indicating if the data object is loading or not
38- **useStatus**(dataObject) - Returns booleans indicating if the data object is saving or deleting records
39- **usePermissions**(dataObject) - Returns booleans indicating if the user can delete, insert or update records
40
41The above hooks uses the data objects internal state to pass data to the components. If you do not want to depend on the data objects current row or data storage, you can use the following hooks. They return data from the data object's data handler directly, and will not affect the data objects internal state.
42
43- **useFetchData**(dataObject, filter) - Returns data matching the filter
44- **useFetchRecord**(dataObject, filter) - Use if the filter is expected to only return a single row. If multiple rows are returned from the server, only the first record will be returned to the component.
45
46One hook is also available for procedures.
47
48- **useProcedure**(procedure, parameters) - Returns an object containing `data`, `isExecuting` and `error` properties. Executes whenever the procedure or parameters arguments change.
49
50### Examples
51
52#### Getting all state from the data object
53
54This will list all reacords in the data object, and create an editor for the current row.
55
56```jsx
57import {
58 useCurrentIndex,
59 useCurrentRow,
60 useData,
61 useDirty,
62 useError,
63 useLoading,
64 useStatus,
65 usePermissions
66} from "@olenbetong/react-data-object-connect";
67
68function MyFunctionComponent(props) {
69 const currentIndex = useCurrentIndex(dsMyDataObject);
70 const myRecord = useCurrentRow(dsMyDataObject);
71 const myRecords = useData(dsMyDataObject);
72 const isDirty = useDirty(dsMyDataObject);
73 const error = useError(dsMyDataObject);
74 const isLoading = useLoading(dsMyDataObject);
75 const { isDeleting, isSaving } = useStatus(dsMyDataObject);
76 const { allowDelete, allowInsert, allowUpdate } = usePermissions(
77 dsMyDataObject
78 );
79
80 return (
81 <div>
82 {isLoading && <i className="fa fa-spin fa-spinner" />}
83 {error && <Error message={error} />}
84 <MyEditor {...myRecord} isDirty={isDirty} />
85 {myRecords.map(record => (
86 <ListItem {...item} />
87 ))}
88 </div>
89 );
90}
91```
92
93Automatically getting data with a given filter
94
95```jsx
96import {
97 useDataWithFilter,
98 useLoading
99} from "@olenbetong/react-data-object-connect";
100
101function MyComponent({ someId }) {
102 const isLoading = useLoading(dsMyDataObject);
103 const data = useDataWithFilter(dsMyDataObject, `[SomeID] = ${someId}`);
104
105 return (
106 <div>
107 {isLoading && <i className="fa fa-spin fa-spinner" />}
108 {data.map(record => (
109 <ListItem {...record} />
110 ))}
111 </div>
112 );
113}
114```
115
116#### Getting data from the data source without affecting the data object
117
118```jsx
119import {
120 useFetchData,
121 useFetchRecord
122} from "@olenbetong/react-data-object-connect";
123
124function MyFunctionComponent(props) {
125 const { isLoading, data, refresh } = useFetchData(
126 dsMyDataObject,
127 `[EntityCategory] = 1`
128 );
129
130 return (
131 <div>
132 {isLoading && <i className="fa fa-spin fa-spinner" />}
133 {data.map(data => (
134 <ListItem {...item} />
135 ))}
136 </div>
137 );
138}
139
140function MyRecordComponent(props) {
141 const { isLoading, record, refresh } = useFetchRecord(
142 dsMyDataObject,
143 `[EntityID] = ${props.id}`
144 );
145
146 return (
147 <div>
148 {isLoading && <Spinner />}
149 <button onClick={refresh}>
150 <i className="fa fa-refresh" /> Refresh
151 </button>
152 <MyEditor {...record} />
153 </div>
154 );
155}
156```
157
158#### Executing a stored procedure
159
160```jsx
161import { useProcedure } from "@olenbetong/react-data-object-connect";
162
163function MyComponent() {
164 const { data, error, isExecuting } = useProcedure(
165 procMyProcedure,
166 {
167 Parameter: "value",
168 OtherParam: 52,
169 ThirdParam: "Oh, hai!"
170 }
171 );
172
173 return (
174 <div>
175 {error && <div className="alert alert-danger">{error}</div>}
176 {isExecuting && <Spinner />}
177 {data && data.length > 0 && data[0].map(record => (
178 <RecordComponent key={record.IdentityField} {...record} />
179 )}
180 )
181}
182```
183
184## connect/connectRow
185
186Use the connect and connectRow functions to create a higher order component that can be used to connect the data object to React components.
187
188The connect function will pass all records to the component in a property named `data`, while the connectRow passes all the fields in the current row as properties to the component.
189
190Example connecting to all records:
191
192```jsx
193import React from "react";
194import { connect } from "@olenbetong/react-data-object-connect";
195
196const MyListComponent = props => (
197 <ul>
198 {props.data.map(item => (
199 <li key={item.PrimKey}>{item.Title}</li>
200 ))}
201 </ul>
202);
203
204const MyConnectedList = connect(dsMyDataObject)(MyListComponent);
205```
206
207Example connecting to a single record, and checking if it is modified:
208
209```jsx
210import React from 'react';
211import { connectRow } from '@olenbetong/react-data-object-connect';
212
213const MyRecordComponent = (props) => (
214 <p>
215 {props.isDirty && <div>(Data not saved</div>)}
216 {props.Title}
217 </p>
218)
219
220const MyConnectedComponent = connectRow(dsMyDataObject)(MyRecordComponent);
221```
222
223### Properties
224
225Status properties passed to the component:
226
227- **canDelete** (bool) whether the data object allows deleting rows
228- **canUpdate** (bool) whether the data object allows updating rows
229- **canInsert** (bool) whether the data object allows inserting rows
230- **currentIndex** (int) current index selected
231- **isDirty** (bool) whether the currently selectec row has been modified
232- **isDeleting** (bool) whether the data object is currently deleting a row
233- **isLoading** (bool) whether the data object is currently loading data
234- **isSaving** (bool) whether the data object is currently saving a record
235- **loadError** (string) error message if the data failed to load
236
237Function properties passed to the component:
238
239- **onCancelEdit** used to cancel all changes made to the current record
240- **onCurrentIndexChange** used to select a row by index
241- **onEndEdit** used to attempt to save changes made to the current record
242- **onDeleteRow** used to delete a row. A component connected to the current row will always delete the current row, otherwise an index can be passed
243- **onFieldChange** used to update a field in the current row (name of field and value as parameters)
244- **onFieldsChange** used to update multiple fields in the current row (object with field names as keys, and values as values)
245- **onRefreshData** used to refresh data
246- **onRefreshRow** used to refresh only the current row
247- **onSetParameter** used to set a parameter on the data object
248
249## Reducing script size
250
251### Bundlers (webpack/rollup/parcel etc.)
252
253In the node package, the scripts are located in the `es` folder, and you can include the parts you need instead of the whole package.
254
255For example, if you only use the `useData` hook, import it like this:
256
257```js
258import useData from "@olenbetong/react-data-object-connect/es/useData";
259```
260
261Or for the `connect`/`connectRow` functions:
262
263```js
264import { connect, connectRow } from "@olenbetong/react-data-object-connect/es/connect";
265```
266
267### Browser
268
269In the `dist/iife` there are a few files you can choose to add. If you only need hooks, use `hooks.min.js`, which exports all the hooks in global variable `dataObjectHooks`. `connect.min.js` exports the connect and connectRow functions in global variable `dataObjectConnect`.
270
271## Changelog
272
273See the GitHub [releases] page
274
275[releases]: https://github.com/olenbetong/react-data-object-connect/releases
\No newline at end of file