diff --git a/README.md b/README.md index ec8c7ba..ffed0f8 100644 --- a/README.md +++ b/README.md @@ -69,10 +69,6 @@ export default class Gallery { And now any time a value inside the POJO changes, the `useObserver` hook will re-render the component. Sweet! -If the values inside the POJO do not change, the `useObserver` hook will not re-render the component. Sweet! - -This is achieved internally by using `setState` with a `hash` of the POJO. You can see this in action by trying to repeatedly click the "Previous Image" button. The `previousImage` command in the `Gallery` will stop changing the `currentImage` when it gets to 0, and since the values inside the POJO are no longer changing, the `hash` method on the object ensures that the React component will not re-render. - Bonus: You can test the heck out of the interaction now without having to mess with any UI testing libraries. ### Asynchrony diff --git a/package.json b/package.json index af5010e..f9dd69f 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,6 @@ "url": "https://github.com/xolvio/pojo-observer/issues" }, "homepage": "https://github.com/xolvio/pojo-observer#readme", - "dependencies": { - "object-hash": "^2.0.0" - }, "devDependencies": { "@babel/cli": "^7.2.3", "@babel/core": "^7.2.2", diff --git a/src/addHash.ts b/src/addHash.ts deleted file mode 100644 index 8891fcd..0000000 --- a/src/addHash.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint-disable no-param-reassign */ -import hash from './hash' - -export function addHash(testClass: T): T { - // eslint-disable-next-line @typescript-eslint/ban-ts-ignore - // @ts-ignore - testClass.hash = function () { - return hash(this) - } - return testClass -} diff --git a/src/hash.spec.ts b/src/hash.spec.ts deleted file mode 100644 index 69e6196..0000000 --- a/src/hash.spec.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint-disable max-classes-per-file */ -import hash from './hash' - -describe('hash', () => { - class Foo { - public x: any - - public y: any - - constructor(x, y) { - this.x = x - this.y = y - } - } - - class Bar { - public x: any - - public y: any - - constructor(x, y) { - this.x = x - this.y = y - } - } - - it('should provide the same hash when the model values are the same', () => { - const foo = new Foo(1, 2) - - const hash1 = hash(foo) - const hash2 = hash(foo) - - expect(hash1).toEqual(hash2) - }) - it('should provide a different hash when model values change', () => { - const foo = new Foo(1, 2) - - const hash1 = hash(foo) - - foo.x = 5 - const hash2 = hash(foo) - - expect(hash1).not.toEqual(hash2) - }) - it('should return a the same hash for different instances of the same class with the same values', () => { - const foo1 = new Foo(1, 2) - const foo2 = new Foo(1, 2) - - expect(hash(foo1)).toEqual(hash(foo2)) - }) - it('should return a different hash for different classes with the same values', function () { - const foo = new Foo(1, 2) - const bar = new Bar(1, 2) - - expect(hash(foo)).not.toEqual(hash(bar)) - }) - it('should return the same hash for different anonymous objects with the same values', () => { - const foo = {x: 1, y: 2} - const bar = {x: 1, y: 2} - - const hash1 = hash(foo) - const hash2 = hash(bar) - - expect(hash1).toEqual(hash2) - }) -}) diff --git a/src/hash.ts b/src/hash.ts deleted file mode 100644 index 83ac35c..0000000 --- a/src/hash.ts +++ /dev/null @@ -1,11 +0,0 @@ -import hash from 'object-hash' - -// You may be wondering why have specs for a library we don't own. -// Reasoning here is that we want our hash implementation to fulfil -// all the specs for the rest of the library to work. It so happens -// that the `object-hash` library does that, but if we ever change -// it or choose to implement our own, then it must pass the specs. - -export default obj => { - return hash(obj) -} diff --git a/src/useObserver.spec.tsx b/src/useObserver.spec.tsx index 1293305..8a025b1 100644 --- a/src/useObserver.spec.tsx +++ b/src/useObserver.spec.tsx @@ -1,11 +1,9 @@ /* eslint-disable max-classes-per-file,react/button-has-type,no-plusplus */ // eslint-disable-next-line @typescript-eslint/no-unused-vars import * as React from 'react' -import {FunctionComponent} from 'react' import {render, act} from '@testing-library/react' import useObserver from './useObserver' import '@testing-library/jest-dom/extend-expect' -import {addHash} from './addHash' test('add hash internally', () => { class TestClass { @@ -213,7 +211,7 @@ test('add hash explicitly', () => { } function ComponentUsingModel({model}: {model: TestClass}) { - const methods = useObserver(addHash(model)) + const methods = useObserver(model) return (
@@ -226,7 +224,7 @@ test('add hash explicitly', () => { } function OtherComponentUsingModel({model}: {model: TestClass}) { - const methods = useObserver(addHash(model)) + const methods = useObserver(model) return (
@@ -551,10 +549,6 @@ test('it should re-render when multi-level depth fields are set to an object who function Component() { useObserver(object) - console.log( - 'GOZDECKI object.field.nested.deep.very', - object?.field?.nested.deep.very - ) return (
@@ -581,7 +575,6 @@ test('it should re-render when multi-level depth fields are set to an object who } }) - console.log('GOZDECKI object.field.nested.deep', object.field.nested.deep) expect(getByTestId('foo')).toHaveTextContent('deeper') act(() => { object.field.nested.deep.very = 'fathoms' diff --git a/src/useObserver.ts b/src/useObserver.ts index 9c8bea5..dfa8913 100644 --- a/src/useObserver.ts +++ b/src/useObserver.ts @@ -1,5 +1,4 @@ import {useCallback, useEffect, useRef, useState} from 'react' -import hash from './hash' import {generateId} from './helpers/generateId' class EventEmitter { @@ -260,11 +259,6 @@ function addId(model: Model): void { }) } -function addHash(model: Model): void { - // eslint-disable-next-line no-param-reassign - if (!model.hash) model.hash = (): string => hash(model) -} - let currentId = 0 export function useUniqueId(): string { @@ -278,11 +272,11 @@ export function useUniqueId(): string { function useReactify(model: Model): Function { const subscriptionId = useUniqueId() - const [, stateChange] = useState(model.hash()) + const [, stateChange] = useState(0) const stateChangeCallback = useCallback(() => { - stateChange(model.hash()) - }, [model]) + stateChange((prev) => prev + 1) + }, []) useEffect(() => { eventEmitter.on(model.__observableId, subscriptionId, stateChangeCallback) @@ -292,7 +286,6 @@ function useReactify(model: Model): Function { } function decorate(model: Model): void { - addHash(model) addId(model) } diff --git a/yarn.lock b/yarn.lock index 3410f5a..2d77312 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8487,11 +8487,6 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-hash@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.0.3.tgz#d12db044e03cd2ca3d77c0570d87225b02e1e6ea" - integrity sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg== - object-inspect@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"