सबसे व्यावहारिक समाधान इसके लिए एक पुस्तकालय का उपयोग करना है जैसे प्रतिक्रिया-माप ।
अद्यतन : अब पता लगाने के लिए एक कस्टम हुक है (जिसे मैंने व्यक्तिगत रूप से आज़माया नहीं है): प्रतिक्रिया-आकार-पता । कस्टम हुक होने के कारण, यह उपयोग करने के लिए अधिक सुविधाजनक लगता है 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>
)
घटकों के बीच आकार में परिवर्तन को संप्रेषित करने के लिए, आप onResize
कॉलबैक पास कर सकते हैं और उन मूल्यों को संग्रहीत कर सकते हैं जो इसे कहीं मिलता है (इन दिनों राज्य को साझा करने का मानक तरीका 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>
)
}
यदि आप वास्तव में पसंद करना चाहते हैं तो अपना खुद का रोल कैसे करें:
एक आवरण घटक बनाएँ जो डोम से मान प्राप्त कर रहा है और विंडो आकार बदलने वाली घटनाओं को सुन रहा है (या घटक जैसा पता लगाता है react-measure
)। आप इसे बताएं कि कौन सा प्रॉप डोम से प्राप्त करता है और एक रेंडर फ़ंक्शन को एक बच्चे के रूप में ले रहा है।
DOM प्रॉप्स पढ़े जाने से पहले आपको जो प्रस्तुत करना होता है उसे माउंट किया जाना चाहिए; जब वे प्रॉप्स शुरुआती रेंडर के दौरान उपलब्ध नहीं होते हैं, तो आप उपयोग करना चाह सकते हैं style={{visibility: 'hidden'}}
ताकि उपयोगकर्ता इसे 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)}/>;
}
}
इसके साथ, चौड़ाई में परिवर्तन का जवाब देना बहुत आसान है:
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
SVG रेंडर करने के लिए सबसे अच्छी जगह है? ऐसा लगता है कि आप क्या चाहते हैंcomponentWillReceiveProps
याcomponentWillUpdate
नहींrender
।