forked from sheetjs/docs.sheetjs.com
		
	Kaioken useAsync hook
				
					
				
			This commit is contained in:
		
							parent
							
								
									833e9363d8
								
							
						
					
					
						commit
						349cc16819
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -12,7 +12,7 @@ init: | ||||
| 
 | ||||
| .PHONY: dev | ||||
| dev: | ||||
| 	cd docz; npm run start -- --host=0.0.0.0; cd .. | ||||
| 	cd docz; npm run start -- --host=0.0.0.0 --no-open; cd .. | ||||
| 
 | ||||
| .PHONY: serve | ||||
| serve: | ||||
|  | ||||
| @ -137,7 +137,7 @@ When the file header is not known in advance, `any` should be used. | ||||
| 
 | ||||
| The SheetJS [`read`](/docs/api/parse-options) and [`sheet_to_json`](/docs/api/utilities/array#array-output) | ||||
| functions simplify state updates. They are best used in the function bodies of | ||||
| `useEffect`[^2] and `useCallback`[^3] hooks. | ||||
| `useAsync`[^2], `useEffect`[^3] and `useCallback`[^4] hooks. | ||||
| 
 | ||||
| A `useEffect` hook can download and update state when a person loads the site: | ||||
| 
 | ||||
| @ -213,6 +213,41 @@ useEffect(() => { (async() => { | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| 
 | ||||
| :::info pass | ||||
| 
 | ||||
| For this particular use case (fetching a file once when the page loads), it is | ||||
| strongly recommended to use the `useAsync` hook: | ||||
| 
 | ||||
| ```ts | ||||
| import { useAsync } from 'kaioken'; | ||||
| import { read, utils } from 'xlsx'; | ||||
| 
 | ||||
| /* Fetch and parse the file */ | ||||
| // highlight-next-line | ||||
| const [ pres, loading, error ] = useAsync<President[]>(async() => { | ||||
|   /* Download from https://docs.sheetjs.com/pres.numbers */ | ||||
|   const f = await fetch("https://docs.sheetjs.com/pres.numbers"); | ||||
|   const ab = await f.arrayBuffer(); | ||||
| 
 | ||||
|   /* parse */ | ||||
|   const wb = read(ab); | ||||
| 
 | ||||
|   /* generate array of presidents from the first worksheet */ | ||||
|   const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet | ||||
|   const data: President[] = utils.sheet_to_json<President>(ws); // generate objects | ||||
| 
 | ||||
|   // highlight-start | ||||
|   /* return data -- essentially setting state */ | ||||
|   return data; | ||||
|   // highlight-end | ||||
| }, []); | ||||
| ``` | ||||
| 
 | ||||
| SheetJS users reported that it is easier to reason about data fetching using the | ||||
| `useAsync` pattern compared to the traditional `useEffect` jujutsu. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| #### Rendering Data | ||||
| 
 | ||||
| Kaioponents typically render HTML tables from arrays of objects. The `TR` table | ||||
| @ -243,7 +278,7 @@ in the example JSX code: | ||||
| 
 | ||||
| The [`writeFile`](/docs/api/write-options) and [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input) | ||||
| functions simplify exporting data. They are best used in the function bodies of | ||||
| `useCallback`[^4] hooks attached to button or other elements. | ||||
| `useCallback`[^5] hooks attached to button or other elements. | ||||
| 
 | ||||
| A callback can generate a local file when a user clicks a button: | ||||
| 
 | ||||
| @ -278,7 +313,84 @@ const exportFile = useCallback(() => { | ||||
| #### Complete Kaioponent | ||||
| 
 | ||||
| This complete Kaioponent example fetches a test file and displays the data in a | ||||
| HTML table. When the export button is clicked, a callback will export a file: | ||||
| HTML table. When the export button is clicked, a callback will export a file. | ||||
| 
 | ||||
| Examples using `useAsync` and `useEffect` with `useState` are shown below: | ||||
| 
 | ||||
| <Tabs groupId="hook"> | ||||
|   <TabItem name="async" value="useAsync"> | ||||
| 
 | ||||
| ```tsx title="src/SheetJSKaiokenAoO.tsx" | ||||
| import { useAsync, useCallback } from "kaioken"; | ||||
| import { read, utils, writeFileXLSX } from 'xlsx'; | ||||
| 
 | ||||
| interface President { | ||||
|   Name: string; | ||||
|   Index: number; | ||||
| } | ||||
| 
 | ||||
| export default function SheetJSKaiokenAoO() { | ||||
|   /* Fetch and parse the file */ | ||||
|   const [ pres, loading, error ] = useAsync<President[]>(async() => { | ||||
|     const f = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer(); | ||||
|     const wb = read(f); // parse the array buffer | ||||
|     const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet | ||||
|     const data = utils.sheet_to_json<President>(ws); // generate objects | ||||
|     return data; | ||||
|   }, []); | ||||
| 
 | ||||
|   /* get state data and export to XLSX */ | ||||
|   const exportFile = useCallback(() => { | ||||
|     const ws = utils.json_to_sheet(pres!); | ||||
|     const wb = utils.book_new(); | ||||
|     utils.book_append_sheet(wb, ws, "Data"); | ||||
|     writeFileXLSX(wb, "SheetJSKaiokenAoO.xlsx"); | ||||
|   }, [pres]); | ||||
| 
 | ||||
|   return (<table><thead><tr><th>Name</th><th>Index</th></tr></thead><tbody> | ||||
|     { /* generate row for each president */ | ||||
|       pres && pres.map(pres => (<tr> | ||||
|         <td>{pres.Name}</td> | ||||
|         <td>{pres.Index}</td> | ||||
|       </tr>)) | ||||
|     } | ||||
|     { /* loading message */ | ||||
|       !pres && loading && ( <tr><td colSpan="2">Loading ...</td></tr> ) | ||||
|     } | ||||
|     { /* error message */ | ||||
|       !pres && !loading && ( <tr><td colSpan="2">{error.message}</td></tr> ) | ||||
|     } | ||||
|   </tbody><tfoot><td colSpan={2}> | ||||
|     <button onclick={exportFile}>Export XLSX</button> | ||||
|   </td></tfoot></table>); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| :::note pass | ||||
| 
 | ||||
| Typically the JSX structure uses ternary expressions for testing status: | ||||
| 
 | ||||
| ```jsx | ||||
| const [ pres, loading, error ] = useAsync(async() => { /* ... */ }); | ||||
| 
 | ||||
| return ( <> | ||||
|   { pres ? ( | ||||
|       <b>Data is loaded</b> | ||||
|     ) : loading ? ( | ||||
|       <b>Loading ...</b> | ||||
|     ) : ( | ||||
|       <b>{error.message}</b> | ||||
|     ) | ||||
|   } | ||||
| </> ); | ||||
| ``` | ||||
| 
 | ||||
| For clarity, the loading and error messages are separated. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
|   </TabItem> | ||||
|   <TabItem name="effect" value="useEffect + useState"> | ||||
| 
 | ||||
| ```tsx title="src/SheetJSKaiokenAoO.tsx" | ||||
| import { useCallback, useEffect, useState } from "kaioken"; | ||||
| @ -323,6 +435,9 @@ export default function SheetJSKaiokenAoO() { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| 
 | ||||
| <details open> | ||||
|   <summary><b>How to run the example</b> (click to hide)</summary> | ||||
| 
 | ||||
| @ -335,7 +450,7 @@ This demo was tested in the following environments: | ||||
| 
 | ||||
| | Kaioken  | ViteJS   | Date       | | ||||
| |:---------|:---------|:-----------| | ||||
| | `0.17.0` | `5.2.10` | 2024-04-20 | | ||||
| | `0.17.0` | `5.2.11` | 2024-05-21 | | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -482,7 +597,7 @@ This demo was tested in the following environments: | ||||
| 
 | ||||
| | Kaioken  | ViteJS   | Date       | | ||||
| |:---------|:---------|:-----------| | ||||
| | `0.17.0` | `5.2.10` | 2024-04-20 | | ||||
| | `0.17.0` | `5.2.11` | 2024-05-21 | | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -565,7 +680,8 @@ will generate a workbook that can be opened in a spreadsheet editor. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| [^1]: See [`useState`](https://kaioken.dev/docs/hooks/usestate) in the Kaioken documentation. | ||||
| [^2]: See [`useEffect`](https://kaioken.dev/docs/hooks/useeffect) in the Kaioken documentation. | ||||
| [^3]: See [`useCallback`](https://kaioken.dev/docs/hooks/usecallback) in the Kaioken documentation. | ||||
| [^4]: See [`useCallback`](https://kaioken.dev/docs/hooks/usecallback) in the Kaioken documentation. | ||||
| [^1]: See [`useState`](https://kaioken.dev/docs/hooks/useState) in the Kaioken documentation. | ||||
| [^2]: See [`useAsync`](https://kaioken.dev/docs/hooks/useAsync) in the Kaioken documentation. | ||||
| [^3]: See [`useEffect`](https://kaioken.dev/docs/hooks/useEffect) in the Kaioken documentation. | ||||
| [^4]: See [`useCallback`](https://kaioken.dev/docs/hooks/useCallback) in the Kaioken documentation. | ||||
| [^5]: See [`useCallback`](https://kaioken.dev/docs/hooks/useCallback) in the Kaioken documentation. | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user