Skip to content

Commit

Permalink
fix(displayname): refactor memo wrapper on functional components
Browse files Browse the repository at this point in the history
Add Readme for React Dev Tools
  • Loading branch information
rolandszoke committed Mar 12, 2020
1 parent 2325326 commit 5fb7631
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 66 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,32 @@ This is not necessary if you use React Router 4.4+. You can find more details an
</details>
<p></p>

<details>
<summary>Usage with React Developer Tools.</summary>
<p></p>

If you want React Developer Tools to recognize your reactive view components with names, you have to pass a **named component** to the `view` wrapper function instead of an anonymous one.

```jsx
import React from 'react';
import { view, store } from 'react-easy-state';
import Table from 'rc-table';
import cloneDeep from 'lodash/cloneDeep';

const user = store({
name: 'Rick',
});

const componentName = () => (
<div>{user.name}</div>
);

export default view(componentName);
```

</details>
<p></p>

<details>
<summary>Passing nested data to third party components.</summary>
<p></p>
Expand Down
63 changes: 0 additions & 63 deletions __tests__/staticProps.test.js

This file was deleted.

115 changes: 115 additions & 0 deletions __tests__/staticProps.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* eslint-disable react/forbid-foreign-prop-types */
/* eslint-disable no-multi-assign */
import React, { Component } from 'react';
import { render, cleanup } from '@testing-library/react/pure';
// eslint-disable-next-line import/no-unresolved
import { view } from 'react-easy-state';
import PropTypes from 'prop-types';

describe('static props', () => {
afterEach(cleanup);

test('view() should proxy defaultProps for class components', () => {
class MyCustomCompName extends Component {
render() {
return <div>{this.props.name}</div>;
}
}

MyCustomCompName.defaultProps = {
name: 'Bob',
};

const WrappedComp = view(MyCustomCompName);
const { container } = render(<WrappedComp />);
expect(container).toHaveTextContent('Bob');
});

test('view() should proxy defaultProps for functional components', () => {
const MyCustomCompName = props => {
return <div>{props.name}</div>;
};

MyCustomCompName.defaultProps = {
name: 'Bob',
};

const WrappedComp = view(MyCustomCompName);
const { container } = render(<WrappedComp />);
expect(container).toHaveTextContent('Bob');
});

test('view() should proxy propTypes for class components', () => {
class MyCustomCompName extends Component {
render() {
return <div>{this.props.name}</div>;
}
}

MyCustomCompName.propTypes = {
name: PropTypes.string.isRequired,
};

const ViewComp = view(MyCustomCompName);

const errorSpy = jest
.spyOn(console, 'error')
.mockImplementation(message =>
expect(message.indexOf('Failed prop type')).not.toBe(-1),
);
render(<ViewComp number="Bob" />);
expect(errorSpy).toHaveBeenCalled();
errorSpy.mockRestore();
});

test('view() should proxy propTypes for functional components', () => {
const MyCustomCompName = props => {
return <div>{props.number}</div>;
};

MyCustomCompName.propTypes = {
number: PropTypes.number.isRequired,
};

const ViewComp = view(MyCustomCompName);

const errorSpy = jest
.spyOn(console, 'error')
.mockImplementation(message =>
expect(message.indexOf('Failed prop type')).not.toBe(-1),
);
render(<ViewComp number="Bob" />);
expect(errorSpy).toHaveBeenCalled();
errorSpy.mockRestore();
});

test('view() should proxy static methods', () => {
class Comp extends Component {
static getDerivedStateFromError() {}

static customMethod() {}
}

const ViewComp = view(Comp);
expect(ViewComp.getDerivedStateFromError).toBe(
Comp.getDerivedStateFromError,
);
expect(ViewComp.customMethod).toBe(Comp.customMethod);
});

test('view() should proxy static getters', () => {
class Comp extends Component {
static get defaultProp() {
return { key: 'value' };
}

static get customProp() {
return { key: 'hello' };
}
}

const ViewComp = view(Comp);
expect(ViewComp.defaultProps).toEqual(Comp.defaultProps);
expect(ViewComp.customProp).toEqual(Comp.customProp);
});
});
6 changes: 3 additions & 3 deletions src/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ export function view(Comp) {
isInsideFunctionComponent = false;
}
};
ReactiveComp.displayName = Comp.displayName || Comp.name;
ReactiveComp = memo(ReactiveComp);
} else {
const BaseComp = isStatelessComp ? Component : Comp;
// a HOC which overwrites render, shouldComponentUpdate and componentWillUnmount
Expand Down Expand Up @@ -170,5 +168,7 @@ export function view(Comp) {
});
}

return ReactiveComp;
return isStatelessComp && hasHooks
? memo(ReactiveComp)
: ReactiveComp;
}

0 comments on commit 5fb7631

Please sign in to comment.