Skip to content

Commit

Permalink
fix: breakpointIndex가 바뀔 때 반응형을 사용하는 컴포넌트만 리랜더링 되도록 한다 (#937)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbvjaos510 authored Feb 2, 2024
1 parent c5a1d3c commit 3c85844
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 79 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useMemo } from 'react';
import type { CurrentTheme } from '@vibrant-ui/theme';
import { isDefined, isRecord } from '@vibrant-ui/utils';
import type { SystemProp } from '../createSystemProp';
Expand Down Expand Up @@ -47,12 +48,11 @@ export const createInterpolation = (systemProps: SystemProp[], defaultProps: any
return result;
};

return ({ theme, breakpointIndex }: { theme: CurrentTheme; breakpointIndex: number }) =>
(props: Record<string, any>) => {
const interpolationResult = childInterpolation({ ...defaultProps, ...props }, theme);
return ({ theme, props }: { theme: CurrentTheme; props: Record<string, any> }) => {
const interpolationResult = useMemo(() => childInterpolation({ ...defaultProps, ...props }, theme), [props, theme]);

return useBuildStyle({ styleObjects: interpolationResult, theme, breakpointIndex });
};
return useBuildStyle({ styleObjects: interpolationResult, theme });
};
};

const mergeResponsiveValue = (original: Record<string, any>[], next: Record<string, any>[]) => {
Expand Down
10 changes: 4 additions & 6 deletions packages/vibrant-core/src/lib/injectContext/injectContext.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import type { CurrentTheme } from '@vibrant-ui/theme';
import { useCurrentTheme } from '../ThemeProvider';
import { useResponsiveValue } from '../useResponsiveValue';

export function injectContext<ReturnType>(
fn: (_: { theme: CurrentTheme; breakpointIndex: number }) => ReturnType
): () => ReturnType {
return () => {
fn: (_: { theme: CurrentTheme; props: Record<string, any> }) => ReturnType
): (props: any) => ReturnType {
return (props: Record<string, any>) => {
const { theme } = useCurrentTheme();
const { breakpointIndex } = useResponsiveValue();

return fn({ theme, breakpointIndex });
return fn({ theme, props });
};
}
8 changes: 2 additions & 6 deletions packages/vibrant-core/src/lib/useBuildStyle/type.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import type { CurrentTheme } from '@vibrant-ui/theme';

type StyleObject = {
export type StyleObject = {
[property: string]: any;
};

export type BuildStyleFn = (_: {
styleObjects: StyleObject[];
theme: CurrentTheme;
breakpointIndex: number;
}) => Record<string, any>;
export type BuildStyleFn = (_: { styleObjects: StyleObject[]; theme: CurrentTheme }) => Record<string, any>;
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
import type { BuildStyleFn } from './type';
import { useResponsiveValue } from '../useResponsiveValue';
import type { BuildStyleFn, StyleObject } from './type';

export const useBuildStyle: BuildStyleFn = ({ styleObjects, breakpointIndex }) =>
styleObjects.slice(0, breakpointIndex + 1).reduce((result, styleObject) => ({ ...result, ...styleObject }), {});
export const useBuildStyle: BuildStyleFn = ({ styleObjects }) => {
if (styleObjects.length < 2) {
return styleObjects[0] ?? {};
}

// eslint-disable-next-line react-hooks/rules-of-hooks
const { breakpointIndex } = useResponsiveValue();

const style: StyleObject = styleObjects
.slice(0, breakpointIndex + 1)
.reduce((result, styleObject) => ({ ...result, ...styleObject }), {});

return style;
};
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { useMemo } from 'react';
import { useCallback } from 'react';
import { createInterpolation } from '../createInterpolation';
import type { SystemProp } from '../createSystemProp';
import { allSystemProps } from '../props';
import { useCurrentTheme } from '../ThemeProvider';
import { useResponsiveValue } from '../useResponsiveValue';

export const useInterpolation = (additionalSystemProps: SystemProp[] = []) => {
const interpolation = createInterpolation(allSystemProps);

export const useInterpolation = () => {
const { theme } = useCurrentTheme();
const { breakpointIndex } = useResponsiveValue();

const interpolation = useMemo(
() => createInterpolation([...allSystemProps, ...additionalSystemProps])({ theme, breakpointIndex }),
[additionalSystemProps, breakpointIndex, theme]
const useInterpolateStyle = useCallback(
(style: Record<string, any>) => interpolation({ theme, props: style }),
[theme]
);

return {
interpolation,
useInterpolateStyle,
};
};
4 changes: 2 additions & 2 deletions packages/vibrant-example-app/src/app/StoryView.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { FC } from 'react';
import { createElement } from 'react';
import { storyNameFromExport } from '@storybook/csf';
import { Title } from '@vibrant-ui/components';
import { Box } from '@vibrant-ui/core';
import { stories } from '../stories';

type ComponentMeta = {
Expand Down Expand Up @@ -65,7 +65,7 @@ export const StoryView: FC<StoryViewProps> = ({ componentName, storyName, compon
const StoryComponent = componentStories[componentName]?.[storyName];

if (!StoryComponent) {
return <Title level={2}>Story Not Found</Title>;
return <Box width={[200, 300]} height={200} backgroundColor="primary" />;
}

return <StoryComponent {...componentProps} />;
Expand Down
21 changes: 11 additions & 10 deletions packages/vibrant-motion/src/lib/Motion/Motion.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,20 @@ export const Motion = withMotionVariation(
style = {},
...restProps
}) => {
const { interpolation } = useInterpolation();
const { useInterpolateStyle } = useInterpolation();
const onEndRef = useSafeDeps(onEnd);

const useNativeDriver = useRef(true);
const fromStyle = useInterpolateStyle(from);
const toStyle = useInterpolateStyle(to);

const interpolatedAnimations = useMemo(() => {
const fromStyle = interpolation(from);
const toStyle = interpolation(to);

return Object.fromEntries(
Object.entries(fromStyle).map(([property]) => [property, [fromStyle[property], toStyle[property]]] as const)
);
}, [JSON.stringify(from), JSON.stringify(to), interpolation]);
const interpolatedAnimations = useMemo(
() =>
Object.fromEntries(
Object.entries(fromStyle).map(([property]) => [property, [fromStyle[property], toStyle[property]]] as const)
),
[JSON.stringify(from), JSON.stringify(to)]
);

const animatedValue = useMemo(() => new Animated.Value(0), []);

Expand Down Expand Up @@ -113,7 +114,7 @@ export const Motion = withMotionVariation(
[children.type]
);

const currentStyle = useMemo(() => interpolation(handleTransformStyle(style)), [style, interpolation]);
const currentStyle = useInterpolateStyle(handleTransformStyle(style));

return (
<AnimatedViewComponent ref={innerRef} style={[currentStyle, animatedStyle]} {...restProps} {...children.props} />
Expand Down
37 changes: 20 additions & 17 deletions packages/vibrant-motion/src/lib/Motion/Motion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,35 @@ import { withMotionVariation } from './MotionProps';

export const Motion = withMotionVariation(
({ innerRef, children, duration, from, to, loop, delay, easing = 'easeOutQuad', onEnd }) => {
const { interpolation } = useInterpolation();
const { useInterpolateStyle } = useInterpolation();
const elementRef = useRef();
const animationRef = useRef<AnimationControls>();
const ref = useComposedRef(innerRef, elementRef);
const { getResponsiveValue } = useResponsiveValue();

const getResponsiveValueRef = useCallbackRef(getResponsiveValue);
const interpolationRef = useCallbackRef(interpolation);
const onEndRef = useCallbackRef(onEnd);

const keyframes = useMemo(
() => {
const fromStyle = interpolation(
Object.fromEntries(Object.entries(from).map(([key, value]) => [key, getResponsiveValue(value)]))
);

const toStyle = interpolation(
Object.fromEntries(Object.entries(to).map(([key, value]) => [key, getResponsiveValue(value)]))
);
const fromStyle = useInterpolateStyle(
useMemo(
() => Object.fromEntries(Object.entries(from).map(([key, value]) => [key, getResponsiveValue(value)])),
// eslint-disable-next-line react-hooks/exhaustive-deps
[JSON.stringify(from), getResponsiveValue]
)
);
const toStyle = useInterpolateStyle(
useMemo(
() => Object.fromEntries(Object.entries(to).map(([key, value]) => [key, getResponsiveValue(value)])),
// eslint-disable-next-line react-hooks/exhaustive-deps
[getResponsiveValue, JSON.stringify(to)]
)
);

return Object.fromEntries(
const keyframes = useMemo(
() =>
Object.fromEntries(
Object.entries(fromStyle).map(([property]) => [property, [fromStyle[property], toStyle[property]]])
);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[JSON.stringify(from), JSON.stringify(to), getResponsiveValueRef, interpolationRef]
),
[fromStyle, toStyle]
);

useIsomorphicLayoutEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import { withTransitionVariation } from './TransitionProp';

export const Transition = withTransitionVariation(
({ innerRef, children, style = {}, animation, duration = 500, easing = 'easeOutQuad', onEnd, ...restProps }) => {
const { interpolation } = useInterpolation();
const { useInterpolateStyle } = useInterpolation();
const reverse = useRef(false);
const isFirstRender = useRef(true);
const onEndRef = useSafeDeps(onEnd);

// eslint-disable-next-line react-hooks/exhaustive-deps
const interpolatedAnimation = useMemo(() => interpolation(animation), [JSON.stringify(animation), interpolation]);
const interpolatedAnimation = useInterpolateStyle(useMemo(() => animation, [JSON.stringify(animation)]));

const useNativeDriver = useRef(true);

Expand Down Expand Up @@ -103,7 +103,7 @@ export const Transition = withTransitionVariation(
[children.type]
);

const currentStyle = useMemo(() => interpolation(handleTransformStyle(style)), [style, interpolation]);
const currentStyle = useInterpolateStyle(handleTransformStyle(style));

return (
<AnimatedViewComponent ref={innerRef} style={[currentStyle, animatedStyle]} {...restProps} {...children.props} />
Expand Down
25 changes: 7 additions & 18 deletions packages/vibrant-motion/src/lib/Transition/Transition.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cloneElement, useEffect, useMemo, useRef, useState } from 'react';
import { cloneElement, useEffect, useMemo, useRef } from 'react';
import { useInterpolation, useResponsiveValue } from '@vibrant-ui/core';
import { useCallbackRef, useComposedRef } from '@vibrant-ui/utils';
import { timingFunctions } from '../constants/timingFunctions';
Expand All @@ -7,16 +7,16 @@ import { withTransitionVariation } from './TransitionProp';

export const Transition = withTransitionVariation(
({ innerRef, children, style = {}, animation, duration = 200, easing = 'easeOutQuad', onEnd }) => {
const { interpolation } = useInterpolation();
const { useInterpolateStyle } = useInterpolation();

const elementRef = useRef<HTMLElement>(null);
const composedRef = useComposedRef(innerRef, elementRef);
const interpolationRef = useCallbackRef(interpolation);
const { getResponsiveValue } = useResponsiveValue();
const onEndRef = useCallbackRef(onEnd);
const [animationStyle, setAnimationStyle] = useState(
interpolation(
Object.fromEntries(Object.entries(animation).map(([key, value]) => [key, getResponsiveValue(value)]))
const animationStyle = useInterpolateStyle(
useMemo(
() => Object.fromEntries(Object.entries(animation).map(([key, value]) => [key, getResponsiveValue(value)])),
[animation, getResponsiveValue]
)
);

Expand All @@ -32,18 +32,7 @@ export const Transition = withTransitionVariation(
return () => element.removeEventListener('transitionend', onEndRef);
}, [onEndRef]);

useEffect(() => {
requestAnimationFrame(() =>
setAnimationStyle(
interpolationRef(
Object.fromEntries(Object.entries(animation).map(([key, value]) => [key, getResponsiveValue(value)]))
)
)
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(animation), interpolationRef]);

const currentStyle = useMemo(() => interpolation(handleTransformStyle(style)), [style, interpolation]);
const currentStyle = useInterpolateStyle(handleTransformStyle(style));
const properties = Object.keys(animationStyle).join(',');

return cloneElement(children, {
Expand Down

0 comments on commit 3c85844

Please sign in to comment.