mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
fix: Grid should support ssr for flex gap (#29586)
* fix: SSR not break Grid * test: Add hydrate test * fix lint
This commit is contained in:
parent
992b99c011
commit
6aaa7be029
@ -3,6 +3,7 @@ import { createContext, Context } from 'react';
|
||||
export interface RowContextState {
|
||||
gutter?: [number, number];
|
||||
wrap?: boolean;
|
||||
supportFlexGap?: boolean;
|
||||
}
|
||||
|
||||
const RowContext: Context<RowContextState> = createContext({});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
import { mount } from 'enzyme';
|
||||
import { Col, Row } from '..';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
@ -26,4 +27,27 @@ describe('Grid.Gap', () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('not break ssr', () => {
|
||||
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const Demo = () => (
|
||||
<Row gutter={[16, 8]}>
|
||||
<Col />
|
||||
</Row>
|
||||
);
|
||||
|
||||
const div = document.createElement('div');
|
||||
|
||||
const ssrTxt = ReactDOMServer.renderToString(<Demo />);
|
||||
div.innerHTML = ssrTxt;
|
||||
|
||||
const wrapper = mount(<Demo />, { hydrateIn: div });
|
||||
|
||||
expect(warnSpy).not.toHaveBeenCalled();
|
||||
|
||||
warnSpy.mockRestore();
|
||||
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
@ -2,7 +2,6 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import RowContext from './RowContext';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { detectFlexGapSupported } from '../_util/styleChecker';
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/14324
|
||||
type ColSpanType = number | string;
|
||||
@ -48,7 +47,7 @@ function parseFlex(flex: FlexType): string {
|
||||
const sizes = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'] as const;
|
||||
const Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const { gutter, wrap } = React.useContext(RowContext);
|
||||
const { gutter, wrap, supportFlexGap } = React.useContext(RowContext);
|
||||
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -112,7 +111,7 @@ const Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {
|
||||
}
|
||||
|
||||
// Vertical gutter use padding when gap not support
|
||||
if (gutter && gutter[1] > 0 && !detectFlexGapSupported()) {
|
||||
if (gutter && gutter[1] > 0 && !supportFlexGap) {
|
||||
const verticalGutter = gutter[1] / 2;
|
||||
mergedStyle.paddingTop = verticalGutter;
|
||||
mergedStyle.paddingBottom = verticalGutter;
|
||||
|
11
components/grid/hooks/useFlexGapSupport.tsx
Normal file
11
components/grid/hooks/useFlexGapSupport.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import * as React from 'react';
|
||||
import { detectFlexGapSupported } from '../../_util/styleChecker';
|
||||
|
||||
export default () => {
|
||||
const [flexible, setFlexible] = React.useState(false);
|
||||
React.useEffect(() => {
|
||||
setFlexible(detectFlexGapSupported());
|
||||
}, []);
|
||||
|
||||
return flexible;
|
||||
};
|
@ -8,7 +8,7 @@ import ResponsiveObserve, {
|
||||
ScreenMap,
|
||||
responsiveArray,
|
||||
} from '../_util/responsiveObserve';
|
||||
import { detectFlexGapSupported } from '../_util/styleChecker';
|
||||
import useFlexGapSupport from './hooks/useFlexGapSupport';
|
||||
|
||||
const RowAligns = tuple('top', 'middle', 'bottom', 'stretch');
|
||||
const RowJustify = tuple('start', 'end', 'center', 'space-around', 'space-between');
|
||||
@ -46,8 +46,11 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
xxl: true,
|
||||
});
|
||||
|
||||
const supportFlexGap = useFlexGapSupport();
|
||||
|
||||
const gutterRef = React.useRef<Gutter | [Gutter, Gutter]>(gutter);
|
||||
|
||||
// ================================== Effect ==================================
|
||||
React.useEffect(() => {
|
||||
const token = ResponsiveObserve.subscribe(screen => {
|
||||
const currentGutter = gutterRef.current || 0;
|
||||
@ -62,6 +65,7 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
return () => ResponsiveObserve.unsubscribe(token);
|
||||
}, []);
|
||||
|
||||
// ================================== Render ==================================
|
||||
const getGutter = (): [number, number] => {
|
||||
const results: [number, number] = [0, 0];
|
||||
const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, 0];
|
||||
@ -102,7 +106,7 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
rowStyle.marginLeft = horizontalGutter;
|
||||
rowStyle.marginRight = horizontalGutter;
|
||||
|
||||
if (detectFlexGapSupported()) {
|
||||
if (supportFlexGap) {
|
||||
// Set gap direct if flex gap support
|
||||
[, rowStyle.rowGap] = gutters;
|
||||
} else {
|
||||
@ -110,8 +114,14 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||
rowStyle.marginBottom = verticalGutter;
|
||||
}
|
||||
|
||||
const rowContext = React.useMemo(() => ({ gutter: gutters, wrap, supportFlexGap }), [
|
||||
gutters,
|
||||
wrap,
|
||||
supportFlexGap,
|
||||
]);
|
||||
|
||||
return (
|
||||
<RowContext.Provider value={{ gutter: gutters, wrap }}>
|
||||
<RowContext.Provider value={rowContext}>
|
||||
<div {...others} className={classes} style={{ ...rowStyle, ...style }} ref={ref}>
|
||||
{children}
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user