Skip to content

Commit

Permalink
fix(useReplicant): shallow copy the value if new value isn't identical
Browse files Browse the repository at this point in the history
When replicant value is object, React DOM does not re-render since the
value update is mutation and the values are identical.
  • Loading branch information
Hoishin committed Mar 3, 2019
1 parent 84d776d commit b042aed
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 8 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,15 @@
"git add"
]
},
"dependencies": {
"lodash.clone": "^4.5.0"
},
"devDependencies": {
"@hoishin/eslint-config-ts": "^0.0.5",
"@hoishin/prettierrc": "^2.1.1",
"@hoishin/tsconfig": "^1.0.0",
"@types/jest": "^24.0.9",
"@types/lodash.clone": "^4.5.5",
"@types/node": "^11.10.4",
"@types/react": "^16.8.6",
"@types/react-dom": "^16.8.2",
Expand Down
22 changes: 14 additions & 8 deletions src/useReplicant/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {useEffect, useState} from 'react';
import clone from 'lodash.clone';

/**
* Subscribe to a replicant, returns tuple of the replicant value and `setValue` function.
Expand All @@ -7,21 +8,26 @@ import {useEffect, useState} from 'react';
* @param repName The name of the replicant to use
* @param initialValue Initial value to pass to `useState` function
*/
export function useReplicant<T>(
export const useReplicant = <T>(
repName: string,
initialValue: T,
): [T, (newValue: T) => void] {
): [T, (newValue: T) => void] => {
// Local state to store replicant value
const [value, setValue] = useState<T>(initialValue);
const [value, updateValue] = useState<T>(initialValue);

// Declare replicant
const replicant = nodecg.Replicant(repName, {
defaultValue: initialValue,
});

// Change handler to listen replicant changes
const changeHandler = (newValue: T) => {
setValue(newValue);
const changeHandler = (newValue: T): void => {
updateValue((oldValue) => {
if (newValue !== oldValue) {
return newValue;
}
return clone(newValue);
});
};

// Uses no state directly, removes listener on unmount
Expand All @@ -33,9 +39,9 @@ export function useReplicant<T>(
}, []);

// Function to set replicant value
const setRepValue = (newValue: T) => {
const updateRepValue = (newValue: T): void => {
replicant.value = newValue;
};

return [value, setRepValue];
}
return [value, updateRepValue];
};
17 changes: 17 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,18 @@
dependencies:
"@types/jest-diff" "*"

"@types/lodash.clone@^4.5.5":
version "4.5.5"
resolved "https://registry.yarnpkg.com/@types/lodash.clone/-/lodash.clone-4.5.5.tgz#ddfb966679f05a302e8a50b3550df076b7dbdb79"
integrity sha512-Hro8TEMNG2VC2F54IoU3sacDpLeeOsi5WhGxBm9Dt4bQrj794Qy6GP7Dft53uX4Mm76keUNyOdD4TEf3aljNyg==
dependencies:
"@types/lodash" "*"

"@types/lodash@*":
version "4.14.121"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.121.tgz#9327e20d49b95fc2bf983fc2f045b2c6effc80b9"
integrity sha512-ORj7IBWj13iYufXt/VXrCNMbUuCTJfhzme5kx9U/UtcIPdJYuvPDUAlHlbNhz/8lKCLy9XGIZnGrqXOtQbPGoQ==

"@types/mime@*":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
Expand Down Expand Up @@ -4388,6 +4400,11 @@ lodash.camelcase@^4.1.1:
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=

lodash.clone@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6"
integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=

lodash.clonedeep@4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
Expand Down

0 comments on commit b042aed

Please sign in to comment.