Skip to content
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
52 changes: 0 additions & 52 deletions __tests__/functionComponent.test.no-hook.jsx

This file was deleted.

76 changes: 76 additions & 0 deletions __tests__/store.no-hook.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { Component } from 'react';
import { render, cleanup } from '@testing-library/react/pure';
// eslint-disable-next-line import/no-unresolved
import { view, store } from 'react-easy-state';

describe('Using an old react version', () => {
afterEach(cleanup);

test(`Using local state in a function component ${
process.env.NOHOOK
? 'with a version of react that has no hooks should'
: 'should not'
} throw an error`, () => {
const MyComp = view(() => {
const person = store({ name: 'Bob' });
return <div>{person.name}</div>;
});

if (process.env.NOHOOK) {
expect(() => render(<MyComp />)).toThrow(
'You cannot use state inside a function component with a pre-hooks version of React. Please update your React version to at least v16.8.0 to use this feature.',
);
} else {
expect(() => render(<MyComp />)).not.toThrow();
}
});

test('Using global state in a function component should not throw an error', () => {
const person = store({ name: 'Bob' });
const MyComp = view(() => {
return <div>{person.name}</div>;
});
expect(() => render(<MyComp />)).not.toThrow();
});

test('Using global state in a class component should not throw an error', () => {
const person = store({ name: 'Bob' });
const MyComp = view(
class extends Component {
render() {
return <div>{person.name}</div>;
}
},
);
expect(() => render(<MyComp />)).not.toThrow();
});

test('Using local state in a class component should not throw an error', () => {
const MyComp = view(
class extends Component {
person = store({ name: 'Bob' });

render() {
return <div>{this.person.name}</div>;
}
},
);

expect(() => render(<MyComp />)).not.toThrow();
});

test('Using local state inside a render of a class component should throw an error', () => {
const MyComp = view(
class extends Component {
render() {
const person = store({ name: 'Bob' });
return <div>{person.name}</div>;
}
},
);

expect(() => render(<MyComp />)).toThrow(
'You cannot use state inside a render of a class component. Please create your store outside of the render function.',
);
});
});
2 changes: 1 addition & 1 deletion jest.no-hook.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"setupFilesAfterEnv": ["./scripts/testSetup.js"],
"testRegex": "\\.test\\.no-hook\\.jsx?$",
"testRegex": "\\.no-hook\\.test\\.jsx?$",
"collectCoverage": true,
"coverageReporters": ["text"],
"collectCoverageFrom": ["src/**/*.{js,jsx}"],
Expand Down
11 changes: 8 additions & 3 deletions src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { observable } from '@nx-js/observer-util';

import {
isInsideFunctionComponent,
isInsideClassComponent,
isInsideClassComponentRender,
isInsideFunctionComponentWithoutHooks,
} from './view';
import { hasHooks } from './utils';

export function store(obj) {
// do not create new versions of the store on every render
Expand All @@ -14,10 +14,15 @@ export function store(obj) {
if (isInsideFunctionComponent) {
return useMemo(() => observable(obj), []);
}
if (!hasHooks && isInsideClassComponent) {
if (isInsideFunctionComponentWithoutHooks) {
throw new Error(
'You cannot use state inside a function component with a pre-hooks version of React. Please update your React version to at least v16.8.0 to use this feature.',
);
}
if (isInsideClassComponentRender) {
throw new Error(
'You cannot use state inside a render of a class component. Please create your store outside of the render function.',
);
}
return observable(obj);
}
9 changes: 6 additions & 3 deletions src/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import { hasHooks } from './utils';
import { queue } from './queue';

export let isInsideFunctionComponent = false;
export let isInsideClassComponent = false;
export let isInsideClassComponentRender = false;
export let isInsideFunctionComponentWithoutHooks = false;
const COMPONENT = Symbol('owner component');
const TRIGGERRENDER = Symbol('trigger render');

Expand Down Expand Up @@ -96,13 +97,15 @@ export function view(Comp) {
};

render() {
isInsideClassComponent = true;
isInsideClassComponentRender = !isStatelessComp;
isInsideFunctionComponentWithoutHooks = isStatelessComp;
try {
return isStatelessComp
? Comp(this.props, this.context)
: super.render();
} finally {
isInsideClassComponent = false;
isInsideClassComponentRender = false;
isInsideFunctionComponentWithoutHooks = false;
}
}

Expand Down