Skip to content

Commit 6d5a595

Browse files
committed
fix!: Console error when using MutableRef from useRef
1 parent 0d0a597 commit 6d5a595

File tree

5 files changed

+85
-70
lines changed

5 files changed

+85
-70
lines changed

dist/index.d.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@ export interface CSVReaderProps {
1414
inputId?: string;
1515
inputName?: string;
1616
inputStyle?: object;
17-
inputRef?: React.LegacyRef<HTMLInputElement>;
1817
label?: string | React.ReactNode;
1918
onError?: (error: Error) => void;
2019
onFileLoaded: (data: Array<any>, fileInfo: IFileInfo, originalFile?: File) => any;
2120
parserOptions?: PapaParse.ParseConfig;
2221
disabled?: boolean;
2322
strict?: boolean;
2423
}
25-
declare const CSVReader: React.FC<CSVReaderProps>;
24+
declare const CSVReader: React.ForwardRefExoticComponent<CSVReaderProps & React.RefAttributes<HTMLInputElement>>;
2625
export default CSVReader;

dist/react-csv-reader.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/react-csv-reader.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.test.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,22 @@ test('prop-types error when give RefObject to inputRef', async () => {
107107
console.error = jest.fn()
108108
const inputRef: React.RefObject<HTMLInputElement> = { current: null }
109109
React.createElement(CSVReader, {
110-
inputRef,
110+
ref: inputRef,
111111
onFileLoaded: (data, fileInfo) => console.dir(data, fileInfo),
112112
})
113113
expect(console.error).toHaveBeenCalledTimes(0)
114114
})
115+
116+
test('prop-types in Production do not error when given MutableRef to inputRef', async () => {
117+
// @ts-ignore
118+
const ProductionCSVReader = (await import('../dist/react-csv-reader')).default as typeof CSVReader
119+
120+
console.error = jest.fn()
121+
const inputRef: React.MutableRefObject<HTMLInputElement> = { current: null }
122+
React.createElement(ProductionCSVReader, {
123+
ref: inputRef,
124+
onFileLoaded: (data, fileInfo) => console.dir(data, fileInfo),
125+
})
126+
127+
expect(console.error).toHaveBeenCalledTimes(0)
128+
})

src/index.tsx

Lines changed: 67 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export interface CSVReaderProps {
1717
inputId?: string
1818
inputName?: string
1919
inputStyle?: object
20-
inputRef?: React.LegacyRef<HTMLInputElement>
2120
label?: string | React.ReactNode
2221
onError?: (error: Error) => void
2322
onFileLoaded: (data: Array<any>, fileInfo: IFileInfo, originalFile?: File) => any
@@ -26,75 +25,79 @@ export interface CSVReaderProps {
2625
strict?: boolean
2726
}
2827

29-
const CSVReader: React.FC<CSVReaderProps> = ({
30-
accept = '.csv, text/csv',
31-
cssClass = 'csv-reader-input',
32-
cssInputClass = 'csv-input',
33-
cssLabelClass = 'csv-label',
34-
fileEncoding = 'UTF-8',
35-
inputId = 'react-csv-reader-input',
36-
inputName = 'react-csv-reader-input',
37-
inputStyle = {},
38-
inputRef,
39-
label,
40-
onError = () => {},
41-
onFileLoaded,
42-
parserOptions = {} as PapaParse.ParseConfig,
43-
disabled = false,
44-
strict = false,
45-
}) => {
46-
const handleChangeFile = (e: React.ChangeEvent<HTMLInputElement>) => {
47-
let reader: FileReader = new FileReader()
48-
const files: FileList = e.target.files!
28+
const CSVReader = React.forwardRef<HTMLInputElement, CSVReaderProps>(
29+
(
30+
{
31+
accept = '.csv, text/csv',
32+
cssClass = 'csv-reader-input',
33+
cssInputClass = 'csv-input',
34+
cssLabelClass = 'csv-label',
35+
fileEncoding = 'UTF-8',
36+
inputId = 'react-csv-reader-input',
37+
inputName = 'react-csv-reader-input',
38+
inputStyle = {},
39+
label,
40+
onError = () => {},
41+
onFileLoaded,
42+
parserOptions = {} as PapaParse.ParseConfig,
43+
disabled = false,
44+
strict = false,
45+
},
46+
inputRef,
47+
) => {
48+
const handleChangeFile = (e: React.ChangeEvent<HTMLInputElement>) => {
49+
let reader: FileReader = new FileReader()
50+
const files: FileList = e.target.files!
4951

50-
if (files.length > 0) {
51-
const fileInfo: IFileInfo = {
52-
name: files[0].name,
53-
size: files[0].size,
54-
type: files[0].type,
55-
}
52+
if (files.length > 0) {
53+
const fileInfo: IFileInfo = {
54+
name: files[0].name,
55+
size: files[0].size,
56+
type: files[0].type,
57+
}
5658

57-
if (strict && accept.indexOf(fileInfo.type) <= 0) {
58-
onError(new Error(`[strict mode] Accept type not respected: got '${fileInfo.type}' but not in '${accept}'`))
59-
return
60-
}
59+
if (strict && accept.indexOf(fileInfo.type) <= 0) {
60+
onError(new Error(`[strict mode] Accept type not respected: got '${fileInfo.type}' but not in '${accept}'`))
61+
return
62+
}
6163

62-
reader.onload = (_event: Event) => {
63-
const csvData = PapaParse.parse(
64-
reader.result as string,
65-
Object.assign(parserOptions, {
66-
error: onError,
67-
encoding: fileEncoding,
68-
}),
69-
)
70-
onFileLoaded(csvData?.data ?? [], fileInfo, files[0])
71-
}
64+
reader.onload = (_event: Event) => {
65+
const csvData = PapaParse.parse(
66+
reader.result as string,
67+
Object.assign(parserOptions, {
68+
error: onError,
69+
encoding: fileEncoding,
70+
}),
71+
)
72+
onFileLoaded(csvData?.data ?? [], fileInfo, files[0])
73+
}
7274

73-
reader.readAsText(files[0], fileEncoding)
75+
reader.readAsText(files[0], fileEncoding)
76+
}
7477
}
75-
}
7678

77-
return (
78-
<div className={cssClass}>
79-
{label && (
80-
<label className={cssLabelClass} htmlFor={inputId}>
81-
{label}
82-
</label>
83-
)}
84-
<input
85-
className={cssInputClass}
86-
type="file"
87-
id={inputId}
88-
name={inputName}
89-
style={inputStyle}
90-
accept={accept}
91-
onChange={handleChangeFile}
92-
disabled={disabled}
93-
ref={inputRef}
94-
/>
95-
</div>
96-
)
97-
}
79+
return (
80+
<div className={cssClass}>
81+
{label && (
82+
<label className={cssLabelClass} htmlFor={inputId}>
83+
{label}
84+
</label>
85+
)}
86+
<input
87+
className={cssInputClass}
88+
type="file"
89+
id={inputId}
90+
name={inputName}
91+
style={inputStyle}
92+
accept={accept}
93+
onChange={handleChangeFile}
94+
disabled={disabled}
95+
ref={inputRef}
96+
/>
97+
</div>
98+
)
99+
},
100+
)
98101

99102
CSVReader.propTypes = {
100103
accept: PropTypes.string,
@@ -105,7 +108,6 @@ CSVReader.propTypes = {
105108
inputId: PropTypes.string,
106109
inputName: PropTypes.string,
107110
inputStyle: PropTypes.object,
108-
inputRef: PropTypes.oneOfType([PropTypes.func, PropTypes.exact({ current: PropTypes.instanceOf(HTMLInputElement) })]),
109111
label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
110112
onError: PropTypes.func,
111113
onFileLoaded: PropTypes.func.isRequired,

0 commit comments

Comments
 (0)