react-native-community / discussions-and-proposals

Discussions and proposals related to the main React Native project
https://reactnative.dev
1.69k stars 129 forks source link

clearing a LayoutAnimation #460

Open stopachka opened 2 years ago

stopachka commented 2 years ago

Introduction

LayoutAnimation is excellent for creating delightful animations.

Details

One issue programmers need to deal with, is that it can be hard to detect when layout happens. Consider:

onPress = (newState) => { 
    LayoutAnimation.spring(); 
    setState(newState);
}

Here, it's likely that setState(newState) triggers a layout. However, if the vdom diffs and finds no change, then no layout will call. This can then introduce a slight bug. If a few minutes later a user makes another interaction, they'll experience an unexpected animation.

Discussion points

So comes the question: what's the best way to say, I expect a LayoutAnimation to happen shortly, cancel if it doesn't?

An imperative api could like this:

 const id = LayoutAnimation.spring(); 
 setTimeout(() => LayoutAnimation.clear(id), 500);

Where a user can manually choose to clear the animation if it hasn't happened by some time.

Am really curious what ya'll think / if you have different ideas.

p-syche commented 2 years ago

Hi @stopachka, I'm struggling to imagine the case where this would happen. Can you elaborate more on your example?

stopachka commented 2 years ago

Hey @p-syche, sure thing! Admittedly a bit unique, but here's one:

function List({activeItemId: trailingActiveItemId}) { 
   const [activeItemId, setActiveItemId] = useState(trailingActiveItemId); 
   const listItems = listFromItemId(activeItemId);
   useEffect(() => {
      if (activeItemId !== trailingActiveItemId) {
         LayoutAnimation.spring();
      }
      setActiveItemId(trailingActiveItemId);
   }, [trailingActiveItemId])
   return <View>{listItems.map(...)}</View>
}

Here, we trigger a LayoutAnimation, when we're about to change activeItemId. However, it's possible that listItems, which derives from activeItemId, doesn't produce a list that's different.

It's possible to avoid this, by triggering a LayoutAnimation based on listItems instead, but I was thinking: "Would it be nice to have some way to "trigger animation", but have it cancel if nothing happens within some period?"

kipertech commented 1 year ago

I can second on this when using with modal, if you forget that there's a pending LayoutAnimation and try to close the modal down (with presentationStyle={'slide'}), it will bug the modal out and you're stuck there.