Skip to content

Commit 5ddb0da

Browse files
committed
Refactor onChange callback handling
1 parent 20b9b82 commit 5ddb0da

File tree

4 files changed

+22
-19
lines changed

4 files changed

+22
-19
lines changed

src/DSVImport.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ describe('DSVImport', () => {
3131
fireEvent.change(textarea, { target: { value: 'Max' } });
3232
}
3333

34-
expect(onChangeMock).toBeCalledTimes(2);
34+
expect(onChangeMock).toBeCalledTimes(1);
3535
expect(onChangeMock).toBeCalledWith([{ email: undefined, forename: 'Max', surname: undefined }]);
3636
});
3737
});

src/DSVImport.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,38 @@
1-
import React, { PropsWithChildren, useReducer } from 'react';
1+
import React, { PropsWithChildren, useReducer, useEffect } from 'react';
22
import { ColumnsType } from './models/column';
3-
import { getDSVImportContext } from './features/context';
3+
import { getDSVImportContext, useDSVImport } from './features/context';
44
import { createSimpleParserMiddleware } from './middlewares/simpleParserMiddleware';
55
import { State } from './models/state';
66

7+
interface EventListenerProps<T> {
8+
onChange?: (value: T[]) => void;
9+
}
10+
11+
const EventListener = <T extends { [key: string]: string }>(props: EventListenerProps<T>) => {
12+
const [context] = useDSVImport<T>();
13+
14+
useEffect(() => {
15+
if (context.parsed && props.onChange) {
16+
props.onChange(context.parsed);
17+
}
18+
});
19+
20+
return null;
21+
};
22+
723
export interface Props<T> {
824
onChange?: (value: T[]) => void;
925
columns: ColumnsType<T>;
1026
}
1127

1228
export const DSVImport = <T extends { [key: string]: string }>(props: PropsWithChildren<Props<T>>) => {
1329
const DSVImportContext = getDSVImportContext<T>();
14-
const middleware = createSimpleParserMiddleware<T>(props.onChange);
30+
const middleware = createSimpleParserMiddleware<T>();
1531
const initialValues: State<T> = { columns: props.columns };
1632

1733
return (
1834
<DSVImportContext.Provider value={useReducer(middleware, initialValues)}>
35+
<EventListener<T> onChange={props.onChange} />
1936
{props.children}
2037
</DSVImportContext.Provider>
2138
);

src/middlewares/simpleParserMiddleware.test.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,4 @@ describe('simpleParserMiddleware', () => {
3434
});
3535
});
3636
});
37-
38-
it('should invoke the onChange callback', () => {
39-
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
40-
const onChangeMock = jest.fn((_value: TestType[]) => {});
41-
const middlewareWithOnChange = createSimpleParserMiddleware<TestType>(onChangeMock);
42-
43-
middlewareWithOnChange(defaultState, { type: 'setRaw', raw: 'Max' });
44-
45-
expect(onChangeMock).toBeCalledTimes(1);
46-
expect(onChangeMock).toBeCalledWith([{ forename: 'Max', surname: undefined, email: undefined }]);
47-
});
4837
});

src/middlewares/simpleParserMiddleware.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,13 @@ const parseData = <T>(value: string, columns: ColumnsType<T>, delimiter: Delimit
2828
});
2929
};
3030

31-
export const createSimpleParserMiddleware = <T>(onChange?: (value: T[]) => void) => {
31+
export const createSimpleParserMiddleware = <T>() => {
3232
return (state: State<T>, action: Actions<T>) => {
3333
let newState = reducer<T>(state, action);
3434

3535
if (action.type === 'setRaw') {
3636
const delimiter = detectDelimiterFromValue(action.raw);
3737
const parsed = parseData<T>(action.raw, state.columns, delimiter);
38-
if (onChange) {
39-
onChange(parsed);
40-
}
4138
newState = reducer<T>(state, { type: 'setParsed', parsed });
4239
}
4340

0 commit comments

Comments
 (0)