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:
二货机器人 2021-03-02 20:29:00 +08:00 committed by GitHub
parent 992b99c011
commit 6aaa7be029
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 6 deletions

View File

@ -3,6 +3,7 @@ import { createContext, Context } from 'react';
export interface RowContextState {
gutter?: [number, number];
wrap?: boolean;
supportFlexGap?: boolean;
}
const RowContext: Context<RowContextState> = createContext({});

View File

@ -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();
});
});

View File

@ -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;

View 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;
};

View File

@ -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>