react구현체쪽에서 freeze설정 옵션이 들어가면 좋을 것 같습니다
전역적으로 context가 앱 전체를 감싸고 있고, 모든 acitivty들이 해당 context의 변화를 감지해야한다고 할 때, 보여지지 않는 화면은 사실 불필요한 render로직이 돌아가는 상황이기 때문에 children을 조작하는 등의 처리로 불필요한 컴포넌트 로직호출을 피할 수 있다면 좋을 것 같습니다. (현재는 스택전체가 display:none처리가 되어있기 때문에 reflow관련 문제는 없겠지만 사용하는 쪽에서 변경되는 상태에 따라 무거운 로직을 돌린다던지, activity 스택이 과하게 쌓였다던지 하는 경우에 퍼포먼스 이슈가 있을 수 있을 것 같습니다)
react-native쪽에서 주로 사용되는 react-native-screens는 react-freeze로 위 이슈를 해결하고 있습니다. 당근의 stackflow에서도 이를 사용하거나, 혹은 편하신 렌더링 suspend처리를 구현하신 뒤 사용자에게 freeze설정 on/off옵션을 제공한다면 유용할 것 같아 이슈남깁니다
(혹시 react구현체쪽의 로직보단 별도 plugin에서 구현하는 것이 설계원칙에 부합하다고 생각되신다면 close해주세요~)
안녕하세요! 혹시 플러그인에 존재하는 wrapActivity() API로 react-freeze를 사용해서 감싸면 될거같은데요. (isActive 또는 isTop 플래그를 통해서 freeze 여부를 판단) 혹시 이렇게는 힘들까요??
const reactFreezePlugin = () = () => ({
key: "react-freeze-plugin",
wrapActivity({ activity }) {
// ...
}
})
stackflow({
// ...
plugins: [
reactFreezePlugin(),
]
})
답변 감사드려요!
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>
);
},
});
아 맞네요! 그리고 추가로 스와이프백 동작에서 freeze를 풀어줘야되겠네요. 고민해보겠습니다!