Skip to content

Fix React 16 issues #269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/linkClass.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,26 @@ const linkArray = (array: Array, styles: Object, configuration: Object) => {

const linkElement = (element: ReactElement, styles: Object, configuration: Object): ReactElement => {
let appendClassName;
let elementIsFrozen;
let elementShallowCopy;

elementShallowCopy = element;

if (Object.isFrozen && Object.isFrozen(elementShallowCopy)) {
elementIsFrozen = true;
if (Array.isArray(elementShallowCopy)) {
return elementShallowCopy.map((arrayElement) => {
return linkElement(arrayElement, styles, configuration);
});
}

// https://github.com/facebook/react/blob/v0.13.3/src/classic/element/ReactElement.js#L131
const elementIsFrozen = Object.isFrozen && Object.isFrozen(elementShallowCopy);
const propsFrozen = Object.isFrozen && Object.isFrozen(elementShallowCopy.props);
const propsNotExtensible = Object.isExtensible && !Object.isExtensible(elementShallowCopy.props);

if (elementIsFrozen) {
// https://github.com/facebook/react/blob/v0.13.3/src/classic/element/ReactElement.js#L131
elementShallowCopy = objectUnfreeze(elementShallowCopy);
elementShallowCopy.props = objectUnfreeze(elementShallowCopy.props);
} else if (propsFrozen || propsNotExtensible) {
elementShallowCopy.props = objectUnfreeze(elementShallowCopy.props);
}

const styleNames = parseStyleName(elementShallowCopy.props.styleName || '', configuration.allowMultiple);
Expand Down Expand Up @@ -76,6 +85,12 @@ const linkElement = (element: ReactElement, styles: Object, configuration: Objec
if (elementIsFrozen) {
Object.freeze(elementShallowCopy.props);
Object.freeze(elementShallowCopy);
} else if (propsFrozen) {
Object.freeze(elementShallowCopy.props);
}

if (propsNotExtensible) {
Object.preventExtensions(elementShallowCopy.props);
}

return elementShallowCopy;
Expand Down
72 changes: 71 additions & 1 deletion tests/linkClass.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable max-nested-callbacks, react/prefer-stateless-function, class-methods-use-this, no-console */
/* eslint-disable max-nested-callbacks, react/prefer-stateless-function, class-methods-use-this, no-console, no-unused-expressions */

import chai, {
expect
Expand Down Expand Up @@ -239,6 +239,76 @@ describe('linkClass', () => {
});
});

context('can\'t write to properties', () => {
context('when the element is frozen', () => {
it('adds className but is still frozen', () => {
let subject;

subject = <div styleName='foo' />;

Object.freeze(subject);
subject = linkClass(subject, {
foo: 'foo-1'
});

expect(subject).to.be.frozen;
expect(subject.props.className).to.equal('foo-1');
});
});
context('when the element\'s props are frozen', () => {
it('adds className and only props are still frozen', () => {
let subject;

subject = <div styleName='foo' />;

Object.freeze(subject.props);
subject = linkClass(subject, {
foo: 'foo-1'
});

expect(subject.props).to.be.frozen;
expect(subject.props.className).to.equal('foo-1');
});
});
context('when the element\'s props are not extensible', () => {
it('adds className and props are still not extensible', () => {
let subject;

subject = <div styleName='foo' />;

Object.preventExtensions(subject.props);
subject = linkClass(subject, {
foo: 'foo-1'
});

expect(subject.props).to.not.be.extensible;
expect(subject.props.className).to.equal('foo-1');
});
});
});

context('when element is an array', () => {
it('handles each element individually', () => {
let subject;

subject = [
<div key={1} styleName='foo' />,
<div key={2}>
<p styleName='bar' />
</div>
];

subject = linkClass(subject, {
bar: 'bar-1',
foo: 'foo-1'
});

expect(subject).to.be.an('array');
expect(subject[0].props.className).to.equal('foo-1');
expect(subject[1].props.children.props.className).to.equal('bar-1');
});
});

describe('options.allowMultiple', () => {
context('when multiple module names are used', () => {
context('when false', () => {
Expand Down