diff --git a/__tests__/functionComponent.test.no-hook.jsx b/__tests__/functionComponent.test.no-hook.jsx
deleted file mode 100644
index 2d5aa14..0000000
--- a/__tests__/functionComponent.test.no-hook.jsx
+++ /dev/null
@@ -1,52 +0,0 @@
-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 with a version of react that has no hooks should throw an error', () => {
- const MyComp = view(() => {
- const person = store({ name: 'Bob' });
- return
{person.name}
;
- });
- expect(() => render()).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.',
- );
- });
-
- test('Using global state in a function component with a version of react that has no hooks should not throw an error', () => {
- const person = store({ name: 'Bob' });
- const MyComp = view(() => {
- return {person.name}
;
- });
- expect(() => render()).not.toThrow();
- });
-
- test('Using global state in a class component with a version of react that has no hooks should not throw an error', () => {
- const person = store({ name: 'Bob' });
- const MyComp = view(
- class extends Component {
- render() {
- return {person.name}
;
- }
- },
- );
- expect(() => render()).not.toThrow();
- });
-
- test('Using local state in a class component with a version of react that has no hooks should not throw an error', () => {
- const MyComp = view(
- class extends Component {
- person = store({ name: 'Bob' });
-
- render() {
- return {this.person.name}
;
- }
- },
- );
-
- expect(() => render()).not.toThrow();
- });
-});
diff --git a/__tests__/store.no-hook.test.jsx b/__tests__/store.no-hook.test.jsx
new file mode 100644
index 0000000..51929e6
--- /dev/null
+++ b/__tests__/store.no-hook.test.jsx
@@ -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 {person.name}
;
+ });
+
+ if (process.env.NOHOOK) {
+ expect(() => render()).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()).not.toThrow();
+ }
+ });
+
+ test('Using global state in a function component should not throw an error', () => {
+ const person = store({ name: 'Bob' });
+ const MyComp = view(() => {
+ return {person.name}
;
+ });
+ expect(() => render()).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 {person.name}
;
+ }
+ },
+ );
+ expect(() => render()).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 {this.person.name}
;
+ }
+ },
+ );
+
+ expect(() => render()).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 {person.name}
;
+ }
+ },
+ );
+
+ expect(() => render()).toThrow(
+ 'You cannot use state inside a render of a class component. Please create your store outside of the render function.',
+ );
+ });
+});
diff --git a/jest.no-hook.json b/jest.no-hook.json
index 08032b2..bac4ac6 100644
--- a/jest.no-hook.json
+++ b/jest.no-hook.json
@@ -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}"],
diff --git a/src/store.js b/src/store.js
index 56c6f30..3810ea9 100644
--- a/src/store.js
+++ b/src/store.js
@@ -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
@@ -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);
}
diff --git a/src/view.js b/src/view.js
index 5063749..6052773 100644
--- a/src/view.js
+++ b/src/view.js
@@ -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');
@@ -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;
}
}