+code: "import React, { useState, useEffect, useRef } from 'react';\r\n\r\n\/\/ Usage\r\nfunction MyComponent({ obj }) {\r\n const [state, setState] = useState();\r\n \r\n \/\/ Use the previous obj value if the \"id\" property hasn't changed\r\n const objFinal = useMemoCompare(obj, (prev, next) => {\r\n return prev && prev.id === next.id;\r\n });\r\n \r\n \/\/ Here we want to fire off an effect if objFinal changes.\r\n \/\/ If we had used obj directly without the above hook and obj was technically a\r\n \/\/ new object on every render then the effect would fire on every render.\r\n \/\/ Worse yet, if our effect triggered a state change it could cause an endless loop\r\n \/\/ where effect runs -> state change causes rerender -> effect runs -> etc ...\r\n useEffect(() => {\r\n \/\/ Call a method on the object and set results to state\r\n return objFinal.someMethod().then((value) => setState(value));\r\n }, [objFinal]);\r\n \r\n \/\/ So why not pass [obj.id] as the dependency array instead?\r\n useEffect(() => {\r\n \/\/ Then eslint-plugin-hooks would rightfully complain that obj is not in the\r\n \/\/ dependency array and we'd have to use eslint-disable-next-line to work around that. \r\n \/\/ It's much cleaner to just get the old object reference with our custom hook.\r\n return obj.someMethod().then((value) => setState(value));\r\n }, [obj.id]);\r\n \r\n return <div> ... <\/div>;\r\n}\r\n \r\n\/\/ Hook\r\nfunction useMemoCompare(next, compare) {\r\n \/\/ Ref for storing previous value\r\n const previousRef = useRef();\r\n const previous = previousRef.current;\r\n \r\n \/\/ Pass previous and next value to compare function\r\n \/\/ to determine whether to consider them equal.\r\n const isEqual = compare(previous, next);\r\n\r\n \/\/ If not equal update previousRef to next value.\r\n \/\/ We only update if not equal so that this hook continues to return\r\n \/\/ the same old value if compare keeps returning true.\r\n useEffect(() => {\r\n if (!isEqual) {\r\n previousRef.current = next;\r\n }\r\n });\r\n \r\n \/\/ Finally, if equal then return the previous value\r\n return isEqual ? previous : next;\r\n}"
0 commit comments