Giải pháp thiết thực nhất là sử dụng một thư viện cho điều này như biện pháp phản ứng .
Cập nhật : hiện có một móc tùy chỉnh để phát hiện thay đổi kích thước (mà tôi chưa thử cá nhân): react-resize-Recognition . Là một móc tùy chỉnh, nó trông thuận tiện hơn để sử dụng hơn react-measure
.
import * as React from 'react'
import Measure from 'react-measure'
const MeasuredComp = () => (
<Measure bounds>
{({ measureRef, contentRect: { bounds: { width }} }) => (
<div ref={measureRef}>My width is {width}</div>
)}
</Measure>
)
Để giao tiếp các thay đổi kích thước giữa các thành phần, bạn có thể chuyển một lệnh onResize
gọi lại và lưu trữ các giá trị mà nó nhận được ở đâu đó (cách chia sẻ trạng thái tiêu chuẩn ngày nay là sử dụng Redux ):
import * as React from 'react'
import Measure from 'react-measure'
import { useSelector, useDispatch } from 'react-redux'
import { setMyCompWidth } from './actions'
export default function MyComp(props) {
const width = useSelector(state => state.myCompWidth)
const dispatch = useDispatch()
const handleResize = React.useCallback(
(({ contentRect })) => dispatch(setMyCompWidth(contentRect.bounds.width)),
[dispatch]
)
return (
<Measure bounds onResize={handleResize}>
{({ measureRef }) => (
<div ref={measureRef}>MyComp width is {width}</div>
)}
</Measure>
)
}
Cách cuộn của riêng bạn nếu bạn thực sự thích:
Tạo một thành phần trình bao bọc xử lý việc nhận các giá trị từ DOM và lắng nghe các sự kiện thay đổi kích thước cửa sổ (hoặc phát hiện thay đổi kích thước thành phần như được sử dụng bởi react-measure
). Bạn cho nó biết đạo cụ nào cần lấy từ DOM và cung cấp chức năng kết xuất lấy các đạo cụ đó khi còn nhỏ.
Những gì bạn kết xuất phải được gắn kết trước khi các đạo cụ DOM có thể được đọc; khi những đạo cụ đó không khả dụng trong lần hiển thị ban đầu, bạn có thể muốn sử dụng style={{visibility: 'hidden'}}
để người dùng không thể nhìn thấy nó trước khi nó có bố cục được tính toán JS.
import React, {Component} from 'react';
import shallowEqual from 'shallowequal';
import throttle from 'lodash.throttle';
type DefaultProps = {
component: ReactClass<any>,
};
type Props = {
domProps?: Array<string>,
computedStyleProps?: Array<string>,
children: (state: State) => ?React.Element<any>,
component: ReactClass<any>,
};
type State = {
remeasure: () => void,
computedStyle?: Object,
[domProp: string]: any,
};
export default class Responsive extends Component<DefaultProps,Props,State> {
static defaultProps = {
component: 'div',
};
remeasure: () => void = throttle(() => {
const {root} = this;
if (!root) return;
const {domProps, computedStyleProps} = this.props;
const nextState: $Shape<State> = {};
if (domProps) domProps.forEach(prop => nextState[prop] = root[prop]);
if (computedStyleProps) {
nextState.computedStyle = {};
const computedStyle = getComputedStyle(root);
computedStyleProps.forEach(prop =>
nextState.computedStyle[prop] = computedStyle[prop]
);
}
this.setState(nextState);
}, 500);
state: State = {remeasure: this.remeasure};
root: ?Object;
componentDidMount() {
this.remeasure();
this.remeasure.flush();
window.addEventListener('resize', this.remeasure);
}
componentWillReceiveProps(nextProps: Props) {
if (!shallowEqual(this.props.domProps, nextProps.domProps) ||
!shallowEqual(this.props.computedStyleProps, nextProps.computedStyleProps)) {
this.remeasure();
}
}
componentWillUnmount() {
this.remeasure.cancel();
window.removeEventListener('resize', this.remeasure);
}
render(): ?React.Element<any> {
const {props: {children, component: Comp}, state} = this;
return <Comp ref={c => this.root = c} children={children(state)}/>;
}
}
Với điều này, phản hồi với các thay đổi chiều rộng rất đơn giản:
function renderColumns(numColumns: number): React.Element<any> {
...
}
const responsiveView = (
<Responsive domProps={['offsetWidth']}>
{({offsetWidth}: {offsetWidth: number}): ?React.Element<any> => {
if (!offsetWidth) return null;
const numColumns = Math.max(1, Math.floor(offsetWidth / 200));
return renderColumns(numColumns);
}}
</Responsive>
);
shouldComponentUpdate
là nơi tốt nhất để hiển thị SVG không? Có vẻ như những gì bạn muốn làcomponentWillReceiveProps
hoặccomponentWillUpdate
nếu khôngrender
.