Skip to content

Commit 6130a6d

Browse files
committed
refactor: modify fileEncoding => encoding & update parserOptions types
1 parent 8ce4722 commit 6130a6d

File tree

3 files changed

+128
-16
lines changed

3 files changed

+128
-16
lines changed

core/README.md

Lines changed: 109 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
react-csv-reader
22
===
33

4-
React component that handles csv file input and its parsing.
4+
[![CI](https://github.com/uiwjs/react-csv-reader/actions/workflows/ci.yml/badge.svg)](https://github.com/uiwjs/react-csv-reader/actions/workflows/ci.yml)
5+
[![npm version](https://img.shields.io/npm/v/@uiw/react-csv-reader.svg)](https://www.npmjs.com/package/@uiw/react-csv-reader)
6+
[![NPM Downloads](https://img.shields.io/npm/dm/@uiw/react-csv-reader.svg?style=flat&label=)](https://www.npmjs.com/package/@uiw/react-csv-reader)
57

8+
React component that handles csv file input and its parsing. <!--rehype:ignore:start-->Example Preview: [uiwjs.github.io/react-csv-reader](https://uiwjs.github.io/react-csv-reader/)<!--rehype:ignore:end-->
69

710
## Quick Start
811

@@ -47,6 +50,8 @@ export default function Demo() {
4750
}
4851
```
4952

53+
**parserOptions**
54+
5055
```tsx mdx:preview
5156
import React, { useState } from 'react';
5257
import CSVReader from '@uiw/react-csv-reader';
@@ -55,12 +60,23 @@ import { lightTheme } from '@uiw/react-json-view/light';
5560
import { darkTheme } from '@uiw/react-json-view/dark';
5661

5762
export default function Demo() {
63+
const [parserOptions, setParserOptions] = useState({
64+
header: true
65+
});
5866
const [value, setValue] = useState([]);
5967
const [fileInfo, setFileInfo] = useState();
6068
const [originalFile, setOriginalFile] = useState();
69+
70+
const change = (evn) => {
71+
console.log('evn:', evn.target.id)
72+
console.log('evn:', evn.target.checked)
73+
74+
setParserOptions({ ...parserOptions, [evn.target.id]: evn.target.checked })
75+
}
6176
return (
6277
<React.Fragment>
6378
<CSVReader
79+
parserOptions={parserOptions}
6480
onFileLoaded={(data, iFileInfo, iOriginalFile) => {
6581
setValue(data);
6682
setFileInfo(iFileInfo);
@@ -71,6 +87,29 @@ export default function Demo() {
7187
setOriginalFile(fileData);
7288
}}
7389
/>
90+
<div style={{ background: '#fff', padding: 10 }}>
91+
<label>
92+
<input type="checkbox" id="stream" checked={!!parserOptions.stream} onChange={change} /> Stream
93+
<p style={{ whiteSpace :'pre-wrap' }}>Results are delivered row by row to a step function. Use with large inputs that would crash the browser.</p>
94+
</label>
95+
<label>
96+
<input type="checkbox" id="worker" checked={!!parserOptions.worker} onChange={change} /> Worker thread
97+
<p style={{ whiteSpace :'pre-wrap' }}>Uses a separate thread so the web page doesn't lock up. </p>
98+
</label>
99+
<label>
100+
<input type="checkbox" id="header" checked={!!parserOptions.header} onChange={change} /> Header row
101+
<p style={{ whiteSpace :'pre-wrap' }}>Keys data by field name rather than an array. </p>
102+
</label>
103+
<label>
104+
<input type="checkbox" id="dynamicTyping" checked={!!parserOptions.dynamicTyping} onChange={change} /> Dynamic typing
105+
<p style={{ whiteSpace :'pre-wrap' }}>Turns numeric data into numbers and true/false into booleans. </p>
106+
</label>
107+
<label>
108+
<input type="checkbox" id="skipEmptyLines" checked={!!parserOptions.skipEmptyLines} onChange={change} /> Skip empty lines
109+
<p style={{ whiteSpace :'pre-wrap' }}>By default, empty lines are parsed; check to skip. </p>
110+
</label>
111+
</div>
112+
74113
{value && value.length > 0 && <JsonView keyName="data" value={value} collapsed={false} style={lightTheme} />}
75114
{fileInfo && <JsonView keyName="fileInfo" value={fileInfo} collapsed={false} style={darkTheme} />}
76115
{originalFile && <JsonView keyName="new File()" value={Object.assign(originalFile)} collapsed={false} style={lightTheme} />}
@@ -82,21 +121,21 @@ export default function Demo() {
82121
## Props
83122

84123
```ts
85-
import { ParseConfig } from 'papaparse';
124+
import { ParseConfig, ParseWorkerConfig, ParseLocalConfig, LocalFile } from 'papaparse';
86125
export interface IFileInfo {
87126
name: string;
88127
size: number;
89128
type: string;
90129
modifiedAt: number;
91130
}
92-
export interface CSVReaderProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onError'> {
131+
export interface CSVReaderProps<T, TFile extends LocalFile = LocalFile> extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onError'> {
93132
strict?: boolean;
94-
fileEncoding?: string;
95-
parserOptions?: ParseConfig;
133+
encoding?: string;
134+
parserOptions?: Partial<ParseWorkerConfig<T>> & Partial<ParseLocalConfig<T>> & ParseConfig<T, TFile>;
96135
onError?: (error: Error) => void;
97-
onFileLoaded: (data: Array<any>, fileInfo: IFileInfo, originalFile?: File) => any;
136+
onFileLoaded: (data: Array<any>, fileInfo: IFileInfo, originalFile?: File) => void;
98137
}
99-
declare const CSVReader: import("react").ForwardRefExoticComponent<CSVReaderProps & import("react").RefAttributes<HTMLInputElement>>;
138+
declare const CSVReader: import("react").ForwardRefExoticComponent<CSVReaderProps<unknown, LocalFile> & import("react").RefAttributes<HTMLInputElement>>;
100139
export default CSVReader;
101140
```
102141

@@ -213,6 +252,69 @@ export interface ParseConfig<T = any, TInput = undefined> {
213252
}
214253
```
215254

255+
```ts
256+
export interface ParseWorkerConfig<T = any> extends ParseConfig<T> {
257+
/**
258+
* Whether or not to use a worker thread.
259+
* Using a worker will keep your page reactive, but may be slightly slower.
260+
*/
261+
worker: true;
262+
/**
263+
* The callback to execute when parsing is complete.
264+
* It receives the parse results. If parsing a local file, the File is passed in, too.
265+
* When streaming, parse results are not available in this callback.
266+
*/
267+
complete(results: ParseResult<T>): void;
268+
}
269+
```
270+
271+
272+
```ts
273+
// Base interface for all async parsing
274+
interface ParseAsyncConfigBase<T = any, TInput = undefined> extends ParseConfig<T, TInput> {
275+
/**
276+
* Whether or not to use a worker thread.
277+
* Using a worker will keep your page reactive, but may be slightly slower.
278+
* @default false
279+
*/
280+
worker?: boolean | undefined;
281+
/**
282+
* Overrides `Papa.LocalChunkSize` and `Papa.RemoteChunkSize`.
283+
*/
284+
chunkSize?: number | undefined;
285+
/**
286+
* A callback function, identical to `step`, which activates streaming.
287+
* However, this function is executed after every chunk of the file is loaded and parsed rather than every row.
288+
* Works only with local and remote files.
289+
* Do not use both `chunk` and `step` callbacks together.
290+
*/
291+
chunk?(results: ParseResult<T>, parser: Parser): void;
292+
/**
293+
* A callback to execute if FileReader encounters an error.
294+
* The function is passed two arguments: the error and the File.
295+
*/
296+
error?(error: Error, file: TInput): void;
297+
}
298+
299+
// Async parsing local file can specify encoding
300+
interface ParseLocalConfigBase<T = any, TInput = undefined> extends ParseAsyncConfigBase<T, TInput> {
301+
/** The encoding to use when opening local files. If specified, it must be a value supported by the FileReader API. */
302+
encoding?: string | undefined;
303+
}
304+
305+
interface ParseLocalConfigStep<T = any, TInput = undefined> extends ParseLocalConfigBase<T, TInput> {
306+
/** @inheritdoc */
307+
step(results: ParseStepResult<T>, parser: Parser): void;
308+
}
309+
interface ParseLocalConfigNoStep<T = any, TInput = undefined> extends ParseLocalConfigBase<T, TInput> {
310+
/** @inheritdoc */
311+
complete(results: ParseResult<T>, file: TInput): void;
312+
}
313+
314+
// Local parsing is async and thus must specify either `step` or `complete` (but may specify both)
315+
export type ParseLocalConfig<T = any, TInput = undefined> = ParseLocalConfigStep<T, TInput> | ParseLocalConfigNoStep<T, TInput>;
316+
```
317+
216318
## Development
217319

218320
Runs the project in development mode.

core/src/index.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { forwardRef } from 'react';
2-
import { parse, ParseConfig } from 'papaparse';
2+
import { parse, ParseConfig, ParseResult, ParseWorkerConfig, ParseLocalConfig, LocalFile } from 'papaparse';
33

44
export interface IFileInfo {
55
name: string;
@@ -8,18 +8,18 @@ export interface IFileInfo {
88
modifiedAt: number;
99
}
1010

11-
export interface CSVReaderProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onError'> {
11+
export interface CSVReaderProps<T, TFile extends LocalFile = LocalFile> extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onError'> {
1212
strict?: boolean;
13-
fileEncoding?: string;
14-
parserOptions?: ParseConfig;
13+
encoding?: string;
14+
parserOptions?: Partial<ParseWorkerConfig<T>> & Partial<ParseLocalConfig<T>> & ParseConfig<T, TFile>;
1515
onError?: (error: Error) => void;
1616
onFileLoaded: (data: Array<any>, fileInfo: IFileInfo, originalFile?: File) => void;
1717
}
1818

19-
const CSVReader = forwardRef<HTMLInputElement, CSVReaderProps>((props, ref) => {
19+
const CSVReader = forwardRef<HTMLInputElement, CSVReaderProps<unknown>>((props, ref) => {
2020
const {
2121
accept = '.csv, text/csv',
22-
fileEncoding = 'UTF-8',
22+
encoding = 'UTF-8',
2323
onError = () => {},
2424
parserOptions = {},
2525
onFileLoaded,
@@ -48,12 +48,12 @@ const CSVReader = forwardRef<HTMLInputElement, CSVReaderProps>((props, ref) => {
4848
const csvData = parse(reader.result as any, {
4949
...parserOptions,
5050
error: onError,
51-
encoding: fileEncoding,
52-
} as ParseConfig);
51+
encoding: encoding,
52+
} as unknown as CSVReaderProps<any, any>['parserOptions']) as unknown as ParseResult<any>;
5353
onFileLoaded && onFileLoaded(csvData?.data ?? [], fileInfo, files[0]);
5454
}
5555

56-
reader.readAsText(files[0], fileEncoding)
56+
reader.readAsText(files[0], encoding)
5757
}
5858
}
5959
return (

www/src/App.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import GitHubCorners from '@uiw/react-github-corners';
22
import { styled } from "goober";
3+
import CSVReader from '@uiw/react-csv-reader';
34
import MarkdownPreview from './Markdown';
45

56
const Header = styled('header')`
@@ -33,6 +34,15 @@ export default function App() {
3334
<h1>
3435
CSV Reader for React<SupVersion>v{VERSION}</SupVersion>
3536
</h1>
37+
<CSVReader
38+
parserOptions={{
39+
// header: true,
40+
// worker: true,
41+
}}
42+
onFileLoaded={(data) => {
43+
console.log('data:', data)
44+
}}
45+
/>
3646
</Header>
3747
<MarkdownPreview />
3848
</Wrappper>

0 commit comments

Comments
 (0)