DEV Community

Andreas Riedmüller
Andreas Riedmüller

Posted on • Edited on

1

usePrevious + useEffect?

Sometimes I need to run a side effect in React when a certain value in the state changes.

I do this quite often and found that for me the most readable (and understandable) method is to use a hook that stores the previous value of something.

export function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
}
Enter fullscreen mode Exit fullscreen mode

Then when I want to create a side effect that only runs when when a specific variable changes:

const [step, setStep] = useState(1);
const [something, setSomething] = useState('Hi world!');
const prevStep = usePrevious(step);

useEffect(() => {
  if (prevStep !== 4 && step === 4) {
    // Do something
  }
}, [step, prevStep, something]);
Enter fullscreen mode Exit fullscreen mode

Does anyone else do it like this way? How often do you need this pattern?

Example

This is one example that I found in a Upload component where I wanted to implement the upload directly in the component. This can be done in a much cleaner way with eg. Redux-Saga

There is a callback onUploaded that should be called when the upload is done.

useEffect(() => {
  if (progress === null) {
    setProgress(0); // This marks the upload as started
    uploadBlob(blob, setProgress).then(() => {
      setBlobUploaded(true);
      onUploaded(); // Dangerous: This might be out of date by the time it's called
    }).catch(reason => {
      setUploadFailedReason(reason);
    });
  }
}, [blob, progress, onUploaded]);
Enter fullscreen mode Exit fullscreen mode
useEffect(() => {
  if (progress === null) {
    setProgress(0); // This marks the upload as started
    uploadBlob(blob, setProgress).then(() => {
      setBlobUploaded(true);
    }).catch(reason => {
      setUploadFailedReason(reason);
    });
  }
}, [blob, progress]);


useEffect(() => {
  if (prevIsBlobUploaded === false && isBlobUploaded === true) {
    onUploaded(); // This is safer, but it's not clear what the state of the blob is
  }
}, [isBlobUploaded, prevIsBlobUploaded, onBlobUploaded]);
Enter fullscreen mode Exit fullscreen mode

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay