Skip to content

Commit 41b876c

Browse files
mbohaladamkudrna
andcommitted
Update blacklisted props that can be passed to native HTML elements using the transferProps principle
Update src/components/_helpers/transferProps.js Co-authored-by: Adam Kudrna <[email protected]> Update src/components/_helpers/transferProps.js Co-authored-by: Adam Kudrna <[email protected]> Update src/components/_helpers/transferProps.js Co-authored-by: Adam Kudrna <[email protected]>
1 parent 5bdd983 commit 41b876c

File tree

2 files changed

+58
-12
lines changed

2 files changed

+58
-12
lines changed

src/components/_helpers/__tests__/transferProps.test.js

+11-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ describe('transferProps', () => {
55
const props = {
66
propA: 'value',
77
propB: 'value',
8-
propC: 'value',
98
};
109
const expectedProps = { ...props };
1110

@@ -14,13 +13,20 @@ describe('transferProps', () => {
1413

1514
it('returns filtered props using always blacklisted props', () => {
1615
const props = {
17-
children: 'value',
1816
className: 'value',
19-
ref: 'value',
20-
staticContext: 'value',
17+
contentEditable: true,
18+
propA: 'value',
2119
};
22-
const expectedProps = {};
20+
const expectedProps = { propA: 'value' };
2321

22+
let errorString;
23+
const originalConsoleError = console.error;
24+
console.error = (error) => {
25+
errorString = error;
26+
};
2427
expect(transferProps(props)).toEqual(expectedProps);
28+
expect(errorString).toEqual('Invalid prop(s) supplied to the "transferProps" function: "className", "contentEditable"');
29+
30+
console.error = originalConsoleError;
2531
});
2632
});
+47-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,47 @@
1-
export const transferProps = ({
2-
children,
3-
className,
4-
ref,
5-
staticContext,
6-
...restProps
7-
}) => restProps;
1+
/**
2+
* Controls passing of props from the React component to the HTML element
3+
*
4+
* Sometimes it is useful to have a mechanism to pass props from the React component to a rendered HTML element.
5+
* It enables making the component interactive and helps improve its accessibility. However some props should
6+
* never be passed to the HTML element as it would break things. This function is used to filter out such props.
7+
*
8+
* When run in development mode, the function will log the error to the console if any invalid props are passed.
9+
*
10+
* @param props The props that were passed to the React component and were not used by it
11+
* @returns The props to be passed to the HTML element
12+
*/
13+
export const transferProps = (props) => {
14+
const {
15+
children,
16+
className,
17+
contentEditable,
18+
dangerouslySetInnerHTML,
19+
ref,
20+
staticContext,
21+
style,
22+
suppressContentEditableWarning,
23+
...restProps
24+
} = props;
25+
26+
if (process.env.NODE_ENV !== 'production') {
27+
console.log('props', props);
28+
const invalidProps = [
29+
'children', // It is always either handled by the component itself or not supported.
30+
'className', // Classes are set by component authors, changing it arbitrarily might break things.
31+
'contentEditable', // Components are either interactive or not, changing it arbitrarily might break things.
32+
'dangerouslySetInnerHTML', // This might break things and allow for XSS attacks.
33+
'ref', // Forwarding `ref` is hardcoded and documented for each component.
34+
'staticContext', // In `react-router` (v4, v5) this is used during server side rendering, it makes no sense to pass it to a component.
35+
'style', // Styles are set by component authors, changing it arbitrarily might break things.
36+
'suppressContentEditableWarning', // Since setting `contentEditable` is not allowed, this is not needed.
37+
]
38+
.filter((key) => props[key] !== undefined);
39+
40+
if (invalidProps.length > 0) {
41+
// eslint-disable-next-line no-console
42+
console.error(`Invalid prop(s) supplied to the "transferProps" function: "${invalidProps.join('", "')}"`);
43+
}
44+
}
45+
46+
return restProps;
47+
};

0 commit comments

Comments
 (0)