Skip to content

Commit 4b62f6d

Browse files
committed
Using shallow copy to unfreeze React element. It is more efficient than React.cloneElement.
1 parent ddfa9a5 commit 4b62f6d

File tree

2 files changed

+24
-31
lines changed

2 files changed

+24
-31
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
},
2121
"license": "BSD-3-Clause",
2222
"dependencies": {
23+
"es6-map": "^0.1.3",
2324
"hoist-non-react-statics": "^1.0.3",
24-
"lodash": "^4.1.0"
25+
"lodash": "^4.1.0",
26+
"object-unfreeze": "^1.0.0"
2527
},
2628
"devDependencies": {
2729
"chai": "^3.5.0",

src/linkClass.js

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,66 +4,57 @@ import makeConfiguration from './makeConfiguration';
44
import isIterable from './isIterable';
55
import parseStyleName from './parseStyleName';
66
import generateAppendClassName from './generateAppendClassName';
7+
import objectUnfreeze from 'object-unfreeze';
78

89
let linkElement;
910

1011
linkElement = (element, styles, configuration) => {
1112
let appendClassName,
12-
children,
13+
elementIsFrozen,
1314
clonedElement,
1415
newChildren,
1516
newProps,
1617
styleNames;
1718

18-
styleNames = parseStyleName(element.props.styleName || '', configuration.allowMultiple);
19+
if (Object.isFrozen && Object.isFrozen(element)) {
20+
elementIsFrozen = true;
1921

20-
if (styleNames.length) {
21-
appendClassName = generateAppendClassName(styles, styleNames, configuration.errorWhenNotFound);
22+
// https://github.com/facebook/react/blob/v0.13.3/src/classic/element/ReactElement.js#L131
23+
element = objectUnfreeze(element);
24+
element.props = objectUnfreeze(element.props);
2225
}
2326

24-
// element.props.children can be one of the following:
25-
// 'text'
26-
// ['text']
27-
// [ReactElement, 'text']
28-
// ReactElement
29-
30-
children = element.props.children;
27+
styleNames = parseStyleName(element.props.styleName || '', configuration.allowMultiple);
3128

32-
if (React.isValidElement(children)) {
33-
newChildren = linkElement(React.Children.only(children), styles, configuration);
34-
} else if (_.isArray(children) || isIterable(children)) {
35-
newChildren = React.Children.map(children, (node) => {
29+
if (React.isValidElement(element.props.children)) {
30+
element.props.children = linkElement(React.Children.only(element.props.children), styles, configuration);
31+
} else if (_.isArray(element.props.children) || isIterable(element.props.children)) {
32+
element.props.children = React.Children.map(element.props.children, (node) => {
3633
if (React.isValidElement(node)) {
3734
return linkElement(node, styles, configuration);
3835
} else {
3936
return node;
4037
}
4138
});
42-
43-
// https://github.com/facebook/react/issues/4723#issuecomment-135555277
44-
// Forcing children into an array produces the following error:
45-
// Warning: A ReactFragment is an opaque type. Accessing any of its properties is deprecated. Pass it to one of the React.Children helpers.
46-
// newChildren = _.values(newChildren);
4739
}
4840

49-
if (appendClassName) {
41+
if (styleNames.length) {
42+
appendClassName = generateAppendClassName(styles, styleNames, configuration.errorWhenNotFound);
43+
5044
if (element.props.className) {
5145
appendClassName = element.props.className + ' ' + appendClassName;
5246
}
5347

54-
newProps = {
55-
className: appendClassName,
56-
styleName: null
57-
};
48+
element.props.className = appendClassName;
49+
element.props.styleName = null;
5850
}
5951

60-
if (newChildren) {
61-
clonedElement = React.cloneElement(element, newProps, newChildren);
62-
} else {
63-
clonedElement = React.cloneElement(element, newProps);
52+
if (elementIsFrozen) {
53+
Object.freeze(element);
54+
Object.freeze(element.props);
6455
}
6556

66-
return clonedElement;
57+
return element;
6758
};
6859

6960
/**

0 commit comments

Comments
 (0)