Last active
August 28, 2021 19:25
-
-
Save gragland/1ed713a68c770ea414c3b92ccf2bdd2f to your computer and use it in GitHub Desktop.
React Hook recipe from https://usehooks.com. Demo: https://codesandbox.io/s/pwnl6v7z6m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useEffect, useRef } from 'react'; | |
// Usage | |
function App() { | |
// State value and setter for our example | |
const [count, setCount] = useState(0); | |
// Get the previous value (was passed into hook on last render) | |
const prevCount = usePrevious(count); | |
// Display both current and previous count value | |
return ( | |
<div> | |
<h1>Now: {count}, before: {prevCount}</h1> | |
<button onClick={() => setCount(count + 1)}>Increment</button> | |
</div> | |
); | |
} | |
// Hook | |
function usePrevious(value) { | |
// The ref object is a generic container whose current property is mutable ... | |
// ... and can hold any value, similar to an instance property on a class | |
const ref = useRef(); | |
// Store current value in ref | |
useEffect(() => { | |
ref.current = value; | |
}, [value]); // Only re-run if value changes | |
// Return previous value (happens before update in useEffect above) | |
return ref.current; | |
} |
hmmm why would you need an initialValue for a usePrevious? it was undefined previously.
This seems to handle all the cases discussed in this thread*:
function usePrevious(value){
const ref = useRef();
useEffect(
() => { ref.current = value; },
[value]
);
return ref.current;
}
* except for initialValue
hmmm why would you need an initialValue for a usePrevious? it was undefined previously.
I have a side effect which calls an API if the current value changes and is different from the previous value. Without initial value, the change is always triggered after first render.
@manzoorwanijk can you give some example code?
…are you doing something like?:
function Image({ src, ...props }){
const prevSrc = usePrevious(src)
useEffect(
()=> {
console.log(`src changed`, {to: src, was: prevSrc})
},
[src]
)
return <img {...props} src={src}/>
}
export default function usePrevious(value) {
// ref value will always be like [prev, state]
let ref = useRef([null, null]);
// storing prev, state values
ref.current.shift()
ref.current.push(value)
// Return previous value
return ref.current[0];
}
@manikanta-kotha it seems like this could be simpler and work the same:
export default function usePrevious(value) {
const ref = useRef();
const prev = ref.current
ref.current = value
return prev;
}
…but it might be nice to always return the previous value. Even on subsequent renders. Like this:
export default function usePrevious(value) {
const ref = useRef();
if (ref.current !== value){
ref.previous = ref.current
ref.current = value
}
return ref.previous;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A better version with support for
initialValue
. Backward compatible with previous version.