Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hook equivalent for getSnapshotBeforeUpdate #15221

Closed
brainkim opened this issue Mar 27, 2019 · 16 comments
Closed

Hook equivalent for getSnapshotBeforeUpdate #15221

brainkim opened this issue Mar 27, 2019 · 16 comments

Comments

@brainkim
Copy link
Contributor

brainkim commented Mar 27, 2019

Do you want to request a feature or report a bug?

Feature

What is the current behavior?

There is no hook based equivalent for getSnapshotBeforeUpdate. The docs state:

Our goal is for Hooks to cover all use cases for classes as soon as possible. There are no Hook equivalents to the uncommon getSnapshotBeforeUpdate and componentDidCatch lifecycles yet, but we plan to add them soon.

What is the expected behavior?

There is a hook based equivalent for getSnapshotBeforeUpdate, maybe something like:

function ScrollingList(props) {
  const lengthRef = React.useRef(0);
  const listRef = React.useRef(null);

  const prevHeight = React.useSnapshot(() => {
    if (lengthRef.current < props.list.length) {
      const list = listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
  }); 

  React.useEffect(() => {
    lengthRef.current = props.list.length;
  }, [props.list.length]);

  React.useEffect(() => {
    if (prevHeight != null) {
      const list = listRef.current;
      list.scrollTop = list.scrollHeight - prevHeight;
    }
  }, [prevHeight]);
  return (
    <div ref={listRef}>{/* ... */}</div>
  );
}

This code probably is bug-ridden and not the best use of hooks but you get the idea.

I’d like to know:

  1. If this feature is planned or on the roadmap.
  2. What the proposed API will be.
  3. If anyone is working on this.

Sorry, if this is being tracked somewhere and I haven’t seen it. I’m planning an intense component which will use getSnapshotBeforeUpdate and I’d love some guidance about the future of this lifecycle method.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

React v16.8.0 and later. All browsers and OSes.

@brainkim
Copy link
Contributor Author

@gaearon Maybe this could be moved to reactjs/rfcs for more visibility?

@voliva
Copy link

voliva commented Oct 15, 2019

It's been almost a year since this hook is marked as "Coming soon™" in the hooks FAQ, but I don't see much movement here... And this would be useful to build hooks that need to run something before the component updates (such as the example which deals with scroll positions before/after update).

Is there any chance this will be looked in the near future™? I completely agree figuring out the API for this hook is a quite hard, so I'm quite sure there will be a big discussion around it.

@stale
Copy link

stale bot commented Jan 13, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution.

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Jan 13, 2020
@brainkim
Copy link
Contributor Author

😭 stale bot why are you like this.

@stale stale bot removed the Resolution: Stale Automatically closed due to inactivity label Jan 13, 2020
@META-DREAMER
Copy link

I hacked around this by using useMemo since that runs the code before the render. For example, to trigger LayoutAnimation in react native:

export const useLayoutAnimation = (
  deps: unknown[],
  easing: LayoutAnimationEasingFunction = 'easeInEaseOut',
) => {
  useMemo(() => {
    LayoutAnimation[easing]();
  }, [...deps, easing]);
};

@ivan7237d
Copy link

The workaround that I use is to have a component like this:

import * as React from 'react';

export class GetSnapshotBeforeUpdate extends React.Component<{
  callback?: VoidFunction;
}> {
  getSnapshotBeforeUpdate = () => {
    this.props.callback?.();
    // Prevents warning.
    return null;
  };

  // Prevents warning.
  componentDidUpdate = () => {};

  render = () => null;
}

and then stick <GetSnapshotBeforeUpdate callback={() => {...} /> into the rendered output of a functional component. If anyone notices any issues with this approach, pls let me know!

BTW I was very surprised that the cleanup function of useLayoutEffect isn't run at the same point as getSnapshotBeforeUpdate.

@stale
Copy link

stale bot commented May 7, 2020

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label May 7, 2020
@stale
Copy link

stale bot commented May 15, 2020

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!

@stale stale bot closed this as completed May 15, 2020
@aweary
Copy link
Contributor

aweary commented Jul 16, 2020

Re-opening as it's still an active feature request

@aweary aweary reopened this Jul 16, 2020
@stale stale bot removed the Resolution: Stale Automatically closed due to inactivity label Jul 16, 2020
@mattgperry
Copy link

What's the current thinking on this? Layout animations are impossible to perform with hooks without this.

@dexbol
Copy link

dexbol commented Mar 29, 2022

It's 2022 now.

@littlepoolshark
Copy link

What is the thing going on? It's 2023 now.

@davidjuhyung
Copy link

June 2023

What's the point of the issue if it will not be responded for more than 4 years?

@brainkim
Copy link
Contributor Author

Closing as unresolvable! Thanks for the feedback!

@pomber
Copy link
Contributor

pomber commented Aug 9, 2023

Closing as unresolvable! Thanks for the feedback!

Why unresolvable @brainkim ?

@ipeterov
Copy link

The current documentation says:

At the moment, there is no equivalent to getSnapshotBeforeUpdate for function components. This use case is very uncommon, but if you have the need for it, for now you’ll have to write a class component.

@sebmarkbage The "for now" implies that this will be resolved in the future, so is it actually planned? Are the docs out of date (it was planned, but now is scrapped), or did you guys close the issue by mistake?

For reference, my use-case is not that rare - all I want to do is infinite scroll in both directions. I needed this exact thing in my current project in multiple places, and in previous projects.

Didn't really know who to ping, sorry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests