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

react구현체쪽에서 freeze설정 옵션이 들어가면 좋을 것 같습니다 #256

Open
YangJonghun opened this issue Oct 30, 2022 · 3 comments

Comments

@YangJonghun
Copy link

YangJonghun commented Oct 30, 2022

전역적으로 context가 앱 전체를 감싸고 있고, 모든 acitivty들이 해당 context의 변화를 감지해야한다고 할 때, 보여지지 않는 화면은 사실 불필요한 render로직이 돌아가는 상황이기 때문에 children을 조작하는 등의 처리로 불필요한 컴포넌트 로직호출을 피할 수 있다면 좋을 것 같습니다.
(현재는 스택전체가 display:none처리가 되어있기 때문에 reflow관련 문제는 없겠지만 사용하는 쪽에서 변경되는 상태에 따라 무거운 로직을 돌린다던지, activity 스택이 과하게 쌓였다던지 하는 경우에 퍼포먼스 이슈가 있을 수 있을 것 같습니다)

react-native쪽에서 주로 사용되는 react-native-screens는 react-freeze로 위 이슈를 해결하고 있습니다. 당근의 stackflow에서도 이를 사용하거나, 혹은 편하신 렌더링 suspend처리를 구현하신 뒤 사용자에게 freeze설정 on/off옵션을 제공한다면 유용할 것 같아 이슈남깁니다

(혹시 react구현체쪽의 로직보단 별도 plugin에서 구현하는 것이 설계원칙에 부합하다고 생각되신다면 close해주세요~)

@tonyfromundefined
Copy link
Member

tonyfromundefined commented Nov 10, 2022

안녕하세요! 혹시 플러그인에 존재하는 wrapActivity() API로 react-freeze를 사용해서 감싸면 될거같은데요. (isActive 또는 isTop 플래그를 통해서 freeze 여부를 판단) 혹시 이렇게는 힘들까요??

const reactFreezePlugin = () = () => ({
  key: "react-freeze-plugin",
  wrapActivity({ activity }) {
    // ...
  }
})
stackflow({
  // ...
  plugins: [
    reactFreezePlugin(),
  ]
})

@YangJonghun
Copy link
Author

YangJonghun commented Nov 10, 2022

답변 감사드려요!

wrapActivity()에서 제공해주시는 activity상태만을 사용해서 처리하기엔 아래와 같은 어려운 부분이 있을 것 같습니다.

freeze(덮여진 activity들의 fallback처리)는 트랜지션이 끝나고 완전히 덮여진 순간에 동작해야만 합니다.

그래야 유저에게 트랜지션 중 정상적인 activity를 보여줄 수 있기 때문인데 이를 위해선 wrapActivity() API에서 최상단 activity의 트랜지션이 끝나는 시점을 감지해야합니다.

하지만 isTop이나 isActive플래그의 경우 transition이 시작되는 순간 false로 변환되기때문에 적합하진 않았습니다.

(useStyleEffectHide에서 display = "none"처리가 되는 시점과 동일한 조건에 freeze처리를 해줘야하는데 wrapActivity에서 제공해주는 값들만으론 이를 처리하기가 애매한것같습니다🥲)

대신 아래와 같이 wrapping component를 추가해 useStack hook의 transitionDuration값을 이용해 트릭을 쓰는 아래와 같은 방법은 가능할 것 같습니다.

function DelayedFreeze({ freeze, children }: FreezeWrapperProps) {
  const [freezeState, setFreezeState] = React.useState(false);
  const stack = useStack();

  if (freeze !== freezeState) {
    setTimeout(() => {
      setFreezeState(freeze);
    }, stack.transitionDuration);
  }

  return <Freeze freeze={freeze ? freezeState : false}>{children}</Freeze>;
}

const reactFreezePlugin: StackflowReactPlugin = ({ initContext }) => ({
  key: "react-freeze-plugin",
  wrapActivity({ activity }) {
    const shouldFreeze = !activity.isActive && !activity.isTop;
    return (
      <DelayedFreeze freeze={shouldFreeze}>{activity.render()}</DelayedFreeze>
    );
  },
});

@tonyfromundefined
Copy link
Member

아 맞네요! 그리고 추가로 스와이프백 동작에서 freeze를 풀어줘야되겠네요. 고민해보겠습니다!

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

No branches or pull requests

2 participants