Skip to content

Commit 4e45886

Browse files
committed
Enhance typing
1 parent 5aa4f82 commit 4e45886

File tree

6 files changed

+43
-29
lines changed

6 files changed

+43
-29
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"react"
88
],
99
"homepage": "https://openscript.github.io/react-dsv-import/",
10-
"version": "0.1.0",
10+
"version": "0.1.1",
1111
"main": "dist/index.js",
1212
"module": "dist/es/index.js",
1313
"types": "dist/index.d.ts",

src/DSVImport.stories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import { DSVImport, ColumnsType, TablePreview, TextareaInput } from './';
3+
import { action } from '@storybook/addon-actions';
34

45
export default { title: 'Usage' };
56

@@ -11,9 +12,11 @@ const columns: ColumnsType<BasicType> = [
1112
{ key: 'email', label: 'Email' }
1213
];
1314

15+
const onChangeAction = action('Parsed value has changed');
16+
1417
export const BasicUsage = () => {
1518
return (
16-
<DSVImport<BasicType> columns={columns}>
19+
<DSVImport<BasicType> columns={columns} onChange={onChangeAction}>
1720
<TextareaInput />
1821
<TablePreview />
1922
</DSVImport>

src/DSVImport.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { PropsWithChildren, useReducer } from 'react';
22
import { ColumnsType } from './models/column';
3-
import { DSVImportContext } from './features/context';
4-
import { SimpleParserMiddleware } from './middlewares/simpleParserMiddleware';
3+
import { getDSVImportContext } from './features/context';
4+
import { createSimpleParserMiddleware } from './middlewares/simpleParserMiddleware';
55
import { State } from './models/state';
66

77
interface Props<T> {
@@ -10,10 +10,12 @@ interface Props<T> {
1010
}
1111

1212
export const DSVImport = <T extends { [key: string]: string }>(props: PropsWithChildren<Props<T>>) => {
13-
const initialValues: State = { columns: props.columns as ColumnsType<{ [key: string]: string }> };
13+
const DSVImportContext = getDSVImportContext<T>();
14+
const middleware = createSimpleParserMiddleware<T>(props.onChange);
15+
const initialValues: State<T> = { columns: props.columns };
1416

1517
return (
16-
<DSVImportContext.Provider value={useReducer(SimpleParserMiddleware, initialValues)}>
18+
<DSVImportContext.Provider value={useReducer(middleware, initialValues)}>
1719
{props.children}
1820
</DSVImportContext.Provider>
1921
);

src/features/context.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { createContext, Dispatch, useContext } from 'react';
33

44
export type Actions = { type: 'setRaw'; raw: string };
55

6-
export const reducer = (state: State, action: Actions) => {
6+
export const reducer = <T>(state: State<T>, action: Actions) => {
77
switch (action.type) {
88
case 'setRaw':
99
return { ...state, raw: action.raw };
@@ -12,10 +12,17 @@ export const reducer = (state: State, action: Actions) => {
1212
}
1313
};
1414

15-
export const DSVImportContext = createContext<[State, Dispatch<Actions>]>([
16-
emptyState,
17-
() => {
18-
throw new Error('Not initialized');
15+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
16+
let contextSingleton: React.Context<[State<any>, Dispatch<Actions>]>;
17+
export const getDSVImportContext = <T>() => {
18+
if (!contextSingleton) {
19+
contextSingleton = createContext<[State<T>, Dispatch<Actions>]>([
20+
(emptyState as unknown) as State<T>,
21+
() => {
22+
throw new Error('Not initialized');
23+
}
24+
]);
1925
}
20-
]);
21-
export const useDSVImport = () => useContext(DSVImportContext);
26+
return contextSingleton as React.Context<[State<T>, Dispatch<Actions>]>;
27+
};
28+
export const useDSVImport = <T = { [key: string]: string }>() => useContext(getDSVImportContext<T>());
Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { State } from '../models/state';
2-
import { Actions } from '../features/context';
2+
import { Actions, reducer } from '../features/context';
33
import { Delimiter } from '../models/delimiter';
44
import { ColumnsType } from '../models/column';
55

@@ -16,29 +16,31 @@ const detectDelimiterFromValue = (value: string, defaultDelimiter = Delimiter.CO
1616
return currentDelimiter;
1717
};
1818

19-
const parseData = <T extends { [key: string]: string }>(
20-
value: string,
21-
columns: ColumnsType<T>,
22-
delimiter: Delimiter
23-
) => {
19+
const parseData = <T>(value: string, columns: ColumnsType<T>, delimiter: Delimiter) => {
2420
const lines = value.split('\n');
2521
return lines.map((line) => {
2622
const lineValues = line.split(delimiter);
2723
const parsedLine: T = {} as T;
2824
columns.forEach((column, columnIndex) => {
29-
parsedLine[column.key] = lineValues[columnIndex] as T[keyof T];
25+
parsedLine[column.key] = (lineValues[columnIndex] as unknown) as T[keyof T];
3026
});
3127
return parsedLine;
3228
});
3329
};
3430

35-
export const SimpleParserMiddleware = <T extends { [key: string]: string }>(state: State<T>, action: Actions) => {
36-
let newState = state;
31+
export const createSimpleParserMiddleware = <T>(onChange?: (value: T[]) => void) => {
32+
return (state: State<T>, action: Actions) => {
33+
let newState = reducer<T>(state, action);
3734

38-
if (action.type === 'setRaw') {
39-
const delimiter = detectDelimiterFromValue(action.raw);
40-
newState = { ...newState, parsed: parseData<T>(action.raw, state.columns, delimiter) };
41-
}
35+
if (action.type === 'setRaw') {
36+
const delimiter = detectDelimiterFromValue(action.raw);
37+
const parsed = parseData<T>(action.raw, state.columns, delimiter);
38+
if (onChange) {
39+
onChange(parsed);
40+
}
41+
newState = { ...newState, parsed };
42+
}
4243

43-
return newState;
44+
return newState;
45+
};
4446
};

src/models/state.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { ColumnsType } from './column';
22

3-
export interface State<T = { [key: string]: string }> {
3+
export interface State<T> {
44
raw?: string;
55
parsed?: T[];
66
columns: ColumnsType<T>;
77
}
88

9-
export const emptyState: State = {
9+
export const emptyState: State<{ [key: string]: string }> = {
1010
columns: []
1111
};

0 commit comments

Comments
 (0)