ReactJS - একটি উপাদানের উচ্চতা পান


121

প্রতিক্রিয়াটি সেই উপাদানটিকে রেন্ডার করার পরে আমি কীভাবে কোনও উপাদানের উচ্চতা পেতে পারি?

এইচটিএমএল

<div id="container">
<!-- This element's contents will be replaced with your component. -->
<p>
jnknwqkjnkj<br>
jhiwhiw (this is 36px height)
</p>
</div>

ReactJS

var DivSize = React.createClass({

  render: function() {
    let elHeight = document.getElementById('container').clientHeight
    return <div className="test">Size: <b>{elHeight}px</b> but it should be 18px after the render</div>;
  }
});

ReactDOM.render(
  <DivSize />,
  document.getElementById('container')
);

ফলাফল

Size: 36px but it should be 18px after the render

এটি রেন্ডার (36px) এর আগে ধারকের উচ্চতা গণনা করছে। আমি রেন্ডারের পরে উচ্চতা পেতে চাই। এই ক্ষেত্রে সঠিক ফলাফলটি 18px হওয়া উচিত। jsfiddle


1
এটি কোনও প্রতিক্রিয়ামূলক প্রশ্ন নয় বরং জাভাস্ক্রিপ্ট এবং ডম প্রশ্ন। আপনার উপাদানটির চূড়ান্ত উচ্চতা খুঁজে পেতে আপনার কোন ডিওএম ইভেন্টটি ব্যবহার করা উচিত তা বোঝার চেষ্টা করা উচিত। ইভেন্ট হ্যান্ডলারটিতে, আপনি setStateউচ্চতার মানটিকে একটি রাষ্ট্রের পরিবর্তনশীলকে নির্ধারণ করতে ব্যবহার করতে পারেন ।
Mostruash

উত্তর:


29

এই ঝাঁকুনিটি দেখুন (আসলে আপনার আপডেট হয়েছে)

componentDidMountরেন্ডার পদ্ধতির পরে আপনাকে চালিত করা দরকার । সেখানে, আপনি উপাদানটির উচ্চতা পাবেন।

var DivSize = React.createClass({
    getInitialState() {
    return { state: 0 };
  },

  componentDidMount() {
    const height = document.getElementById('container').clientHeight;
    this.setState({ height });
  },

  render: function() {
    return (
        <div className="test">
        Size: <b>{this.state.height}px</b> but it should be 18px after the render
      </div>
    );
  }
});

ReactDOM.render(
  <DivSize />,
  document.getElementById('container')
);
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>

<div id="container">
<p>
jnknwqkjnkj<br>
jhiwhiw (this is 36px height)
</p>
    <!-- This element's contents will be replaced with your component. -->
</div>

15
সঠিক না. পল ভিনসেন্ট
বেইগাংয়ের

1
আইএমএইচও, কোনও উপাদান তার
অ্যান্ড্রেস

156

রেফ ব্যবহার করে নীচে একটি আপ টু ডেট ES6 উদাহরণ ।

মনে রাখবেন যে আমাদের একটি লাইকসাইকেল পদ্ধতি অ্যাক্সেস করতে হবে বলে আমাদের একটি প্রতিক্রিয়া শ্রেণি উপাদান ব্যবহার করতে হবে componentDidMount()কারণ আমরা কোনও উপাদান ডিওমে রেন্ডার করার পরে কেবল তার উচ্চতা নির্ধারণ করতে পারি।

import React, {Component} from 'react'
import {render} from 'react-dom'

class DivSize extends Component {

  constructor(props) {
    super(props)

    this.state = {
      height: 0
    }
  }

  componentDidMount() {
    const height = this.divElement.clientHeight;
    this.setState({ height });
  }

  render() {
    return (
      <div 
        className="test"
        ref={ (divElement) => { this.divElement = divElement } }
      >
        Size: <b>{this.state.height}px</b> but it should be 18px after the render
      </div>
    )
  }
}

render(<DivSize />, document.querySelector('#container'))

আপনি চলমান উদাহরণটি এখানে পেতে পারেন: https://codepen.io/bassgang/pen/povzjKw


6
এটি কাজ করে তবে আমি এয়ারবিএনবি স্টাইলগাইডের জন্য বেশ কয়েকটি এসিলিন্ট ত্রুটিগুলি পাচ্ছি: <div ref={ divElement => this.divElement = divElement}>{children}</div>"[এসলিন্ট] তীর ফাংশনটি অ্যাসাইনমেন্টটি ফিরিয়ে দেওয়া উচিত নয় this.setState({ height });( হয়নি-mount-সেট-রাষ্ট্র) "। স্টাইলগাইড-কমপ্লায়েন্ট সলিউশন কেউ পেয়েছেন?
টিমো

7
ব্রেসগুলিতে অ্যাসাইনমেন্টটি মোড়ানো যাতে এটি কোনও ক্রিয়াকলাপের (যেমন একটি এক্সপ্রেশন নয়) হিসাবে আচরণ করে, যেমনref={ divElement => {this.divElement = divElement}}
টেলিটিপিস্ট

3
এটি গ্রহণযোগ্য উত্তর হ'ল :) তদ্ব্যতীত, আপনি উপাদানটি আপডেট হওয়ার পরে যদি উপাদানটির আকার পেতে চান তবে আপনি পদ্ধতিটিও ব্যবহার করতে পারেন componentDidUpdate
jjimenez

4
এই উদাহরণটির সাথে কম্পোনেন্টডিডমাউন্টে এই.সেটস্টেট () কল করার বিকল্প নেই?
danjones_mcr

3
ভাল সমাধান। তবে প্রতিক্রিয়াশীল ডিজাইনের জন্য কাজ করবে না। যদি ডেস্কটপের জন্য শিরোনামের উচ্চতা 50px হয় এবং ব্যবহারকারী উইন্ডোর আকার সঙ্কুচিত করে এবং এখন উচ্চতা 100px হয়ে যায়, এই সমাধানটি আপডেট হওয়া উচ্চতা গ্রহণ করবে না। পরিবর্তিত প্রভাবগুলি পেতে তাদের পৃষ্ঠাটি রিফ্রেশ করতে হবে।
TheCoder

96

যারা ব্যবহার করতে আগ্রহী তাদের react hooksজন্য এটি আপনাকে শুরু করতে সহায়তা করতে পারে।

import React, { useState, useEffect, useRef } from 'react'

export default () => {
  const [height, setHeight] = useState(0)
  const ref = useRef(null)

  useEffect(() => {
    setHeight(ref.current.clientHeight)
  })

  return (
    <div ref={ref}>
      {height}
    </div>
  )
}

11
আপনার উত্তরের জন্য ধন্যবাদ - এটি আমাকে শুরু করতে সহায়তা করেছিল। যদিও 2 টি প্রশ্ন: (1) এই লেআউট-মাপার কাজের জন্য, আমাদের useLayoutEffectপরিবর্তে ব্যবহার করা উচিত useEffect? দস্তাবেজগুলি মনে করে যে আমাদের উচিত। এখানে "টিপ" বিভাগটি দেখুন: reactjs.org/docs/hooks-effect.html# বিবরণী- এক্সপ্ল্যানেশন (২) এই ক্ষেত্রে যেখানে আমাদের কেবলমাত্র একটি শিশু উপাদানের রেফারেন্স প্রয়োজন, সেখানে কি আমাদের useRefপরিবর্তে ব্যবহার করা উচিত createRef? useRefএই ব্যবহারের ক্ষেত্রে ডকগুলি আরও উপযুক্ত বলে মনে হয় । দেখুন: reactjs.org/docs/hooks-references.html#useref
জেসন ফ্রাঙ্ক

আমি সবেমাত্র একটি সমাধান প্রয়োগ করেছি যা আমি প্রস্তাব করছি দুটি আইটেম ব্যবহার করে। তারা ভাল কাজ করছে বলে মনে হচ্ছে, তবে আপনি এই পছন্দগুলির কিছু ডাউনসাইড সম্পর্কে জানেন? আপনার সাহায্যের জন্য ধন্যবাদ!
জেসন ফ্রাঙ্ক

4
@ জেসনফ্রেঙ্ক ভাল প্রশ্ন। 1) ব্যবহার এবং প্রভাব উভয়ই লেআউট এবং পেইন্টের পরে বরখাস্ত করা হবে। তবে, ব্যবহারের লেআউটএফেক্টটি পরবর্তী রঙের আগে সিঙ্ক্রোনজ ফায়ার করবে। আমি বলব যদি আপনার যদি সত্যই ভিজ্যুয়াল ধারাবাহিকতা প্রয়োজন হয় তবে ইউজলয়আউটএফেক্ট ব্যবহার করুন, অন্যথায়, ইউজএফেক্টটি যথেষ্ট হবে। 2) আপনি ঠিক সে সম্পর্কে! ক্রিয়ামূলক উপাদানটিতে ক্রিয়েটরিফ প্রতিটি সময় উপাদানটি রেন্ডার হওয়ার সাথে সাথে একটি নতুন রেফ তৈরি করবে। ইউজারফ ব্যবহার করা আরও ভাল বিকল্প। আমি আমার উত্তর আপডেট করব। ধন্যবাদ!
মিঃ 14

এটি আমাকে কীভাবে হুকস সহ একটি রেফ ব্যবহার করতে হবে তা বুঝতে সহায়তা করেছে। আমি useLayoutEffectএখানে অন্যান্য মন্তব্য পড়ার পরে শেষ পর্যন্ত । ভাল কাজ মনে হচ্ছে। :)
গুইডুডি

1
আমি আমার উপাদানটির মাত্রা নির্ধারণ করছিলাম useEffect(() => setDimensions({width: popup.current.clientWidth, height: popup.current.clientHeight}))এবং আমার আইডিই (ওয়েবস্টোরম) আমাকে এটি প্রস্তাব করেছিল: ইসলিন্ট: প্রতিক্রিয়া হুক ব্যবহারের প্রভাবটিতে 'সেটডাইমেনশনস' এর কল রয়েছে। নির্ভরতার তালিকা ছাড়াই, এটি আপডেটের অসীম শৃঙ্খলে নিয়ে যেতে পারে। এটি ঠিক করতে, [কার্যকর] হুকের দ্বিতীয় তর্ক হিসাবে পাস করুন []। (প্রতিক্রিয়া[]useEffect
হুকস

9

আপনি ব্যবহারের পরিবর্তে উপাদানের উপর রেফ ব্যবহার করতে চাইবেন document.getElementById, এটি কিছুটা বেশি শক্তিশালী জিনিস।


@ ডাবলজোশ মূলত আপনি ঠিকই আছেন তবে উদাহরণস্বরূপ angularJsএবং reactএক থেকে অন্য স্থানে যাওয়ার সময় আপনার কী দরকার ? এমন ঘটনা আছে যেখানে সরাসরি
ডিওএম

2

আমার 2020 এর (বা 2019) উত্তর

import React, {Component, useRef, useLayoutEffect} from 'react';
import { useDispatch } from 'react-redux';
import { Toast, ToastBody, ToastHeader } from 'reactstrap';

import {WidgetHead} from './WidgetHead';

export const Widget = ({title, toggle, reload, children, width, name}) => {
    let myself = useRef(null);
    const dispatch = useDispatch();
    useLayoutEffect(()=>{
        if (myself.current) {
            const height = myself.current.clientHeight
            dispatch({type:'GRID_WIDGET_HEIGHT', widget:name, height})
        }
    }, [myself.current, myself.current?myself.current.clientHeight:0])

    return (
        <Toast innerRef={myself}>
            <WidgetHead title={title}
                toggle={toggle}
                reload={reload} />
            <ToastBody>
            {children}
            </ToastBody>
        </Toast>
    )
}

এখানে (WidgetHead) কি অনুপস্থিত জন্য আপনার কল্পনা ব্যবহার করার অনুমতি, reactstrapপ্রতিস্থাপন করুন: কোন কিছু যা আপনি npm খুঁজে পেতে পারেন হয় innerRefসঙ্গে refএকটি লিগ্যাসি DOM উপাদান জন্য (ক বলে <div>)।

UseEffect বা UseLayoutEffect

শেষটি পরিবর্তনগুলির জন্য সিঙ্ক্রোনাস হিসাবে বলা হয়

useLayoutEffect(বা useEffect) দ্বিতীয় যুক্তি

দ্বিতীয় আর্গুমেন্ট একটি অ্যারে, এবং প্রথম আর্গুমেন্টে ফাংশনটি সম্পাদন করার আগে এটি পরীক্ষা করা হয়।

আমি ব্যবহার করতাম

[নিজেই কর্নার, নিজেই ক্রোড়ন? নিজেই কর্নার.ক্লিয়েন্টহাইট: ০]

কারণ আমার.কমেন্ট বর্তমান রেন্ডারিংয়ের পূর্বে নাল, এবং এটি যাচাই করা ভাল নয়, শেষের দ্বিতীয় প্যারামিটারটি myself.current.clientHeightআমি পরিবর্তনগুলির জন্য যাচাই করতে চাই।

আমি এখানে কী সমাধান করছি (বা সমাধানের চেষ্টা করছি)

আমি এখানে একটি গ্রিডে উইজেটের সমস্যাটি সমাধান করছি যা তাদের নিজস্ব ইচ্ছায় এর উচ্চতা পরিবর্তন করে এবং গ্রিড সিস্টেমটি প্রতিক্রিয়া জানাতে যথেষ্ট স্থিতিস্থাপক হওয়া উচিত ( https://github.com/STRML/react-grid-layout )।


1
দুর্দান্ত উত্তর, তবে সহজ উদাহরণ থেকে উপকৃত হত। মূলত হোয়াইট নাইটের উত্তর কিন্তু সাথে useLayoutEffectএবং সত্যিকারের ডিভের সাথে রেফ টাই করুন।
বট 19

1

হুক সহ ব্যবহার:

লোড হওয়ার পরে যদি আপনার সামগ্রীর মাত্রা পরিবর্তন হয় তবে এই উত্তরটি সহায়ক হবে।

অনড্রেসেটেটেঞ্জিং : ঘটে থাকে যখন কোনও উপাদান বা কোনও HTML ডকুমেন্টের অন্তর্ভুক্ত ডেটার লোডের স্থিতি পরিবর্তন হয়। পৃষ্ঠার সামগ্রীর লোডের স্থিতি পরিবর্তিত হয়ে গেলে অনপরেস্টেটেঞ্চ ইভেন্টটি এইচটিএমএল ডকুমেন্টে নিক্ষেপ করা হয়।

import {useState, useEffect, useRef} from 'react';
const ref = useRef();
useEffect(() => {
    document.onreadystatechange = () => {
      console.log(ref.current.clientHeight);
    };
  }, []);

আমি এমন একটি ইউটিউব ভিডিও প্লেয়ার এম্বেড করার সাথে কাজ করার চেষ্টা করছিলাম যার লোড হওয়ার পরে তার মাত্রা পরিবর্তন হতে পারে।


0

আমি দরকারী এনএমপি প্যাকেজটি পেয়েছি https://www.npmjs.com/package/element-resize-detector

উপাদানগুলির জন্য একটি অপ্টিমাইজড ক্রস ব্রাউজার পুনরায় আকার শোনার।

এটি প্রতিক্রিয়া উপাদান বা কার্যকরী উপাদান দিয়ে ব্যবহার করতে পারেন (প্রতিক্রিয়া হুক জন্য বিশেষভাবে দরকারী)


0

আপনার যদি উইন্ডোর পুনরায় আকারের ইভেন্টের প্রয়োজন হয় তবে এটি আবার একটি:

class DivSize extends React.Component {

  constructor(props) {
    super(props)

    this.state = {
      width: 0,
      height: 0
    }
    this.resizeHandler = this.resizeHandler.bind(this);
  }

  resizeHandler() {
    const width = this.divElement.clientWidth;
    const height = this.divElement.clientHeight;
    this.setState({ width, height });
  }

  componentDidMount() {
    this.resizeHandler();
    window.addEventListener('resize', this.resizeHandler);
  }

  componentWillUnmount(){
    window.removeEventListener('resize', this.resizeHandler);
  }

  render() {
    return (
      <div 
        className="test"
        ref={ (divElement) => { this.divElement = divElement } }
      >
        Size: widht: <b>{this.state.width}px</b>, height: <b>{this.state.height}px</b>
      </div>
    )
  }
}

ReactDOM.render(<DivSize />, document.querySelector('#container'))

কোড পেন


0

একটি বিকল্প সমাধান, আপনি যদি উপাদানটির দৃশ্যমানভাবে রেন্ডার না করে সিঙ্ক্রোনিকভাবে একটি প্রতিক্রিয়ার উপাদানটির আকার পুনরুদ্ধার করতে চান তবে আপনি রিঅ্যাক্টডোএমএসবার এবং ডোম পার্সার ব্যবহার করতে পারেন ।

আমি একটি ফিক্সডসাইজলিস্টের জন্য প্রয়োজনীয় প্রপকে হার্ডকোড না করে প্রতিক্রিয়া-উইন্ডো ( রিঅ্যাক্ট -ভার্চুয়ালাইজড ) ব্যবহার করার সময় আমার তালিকা আইটেমটি রেন্ডারারের উচ্চতা পেতে এই ফাংশনটি ব্যবহার করি ।itemSize

utilities.js:

/**
 * @description Common and reusable functions 
 * 
 * @requires react-dom/server
 * 
 * @public
 * @module
 * 
 */
import ReactDOMServer from "react-dom/server";

/**
 * @description Retrieve the width and/or heigh of a React element without rendering and committing the element to the DOM.
 * 
 * @param {object} elementJSX - The target React element written in JSX.
 * @return {object} 
 * @public
 * @function
 * 
 * @example
 * 
 * const { width, height } = getReactElementSize( <div style={{ width: "20px", height: "40px" }} ...props /> );
 * console.log(`W: ${width}, H: ${height});  // W: 20, H: 40
 * 
 */
const getReactElementSize = (elementJSX) => {

    const elementString = ReactDOMServer.renderToStaticMarkup(elementJSX);
    const elementDocument = new DOMParser().parseFromString(elementString, "text/html");
    const elementNode = elementDocument.getRootNode().body.firstChild;

    const container = document.createElement("div");
    const containerStyle = {

        display: "block",
        position: "absolute",
        boxSizing: "border-box",
        margin: "0",
        padding: "0",
        visibility: "hidden"
    };

    Object.assign(container.style, containerStyle);

    container.appendChild(elementNode);
    document.body.appendChild(container);

    const width = container.clientWidth;
    const height = container.clientHeight;

    container.removeChild(elementNode);
    document.body.removeChild(container);

    return {

        width,
        height
    };
};

/**
 * Export module
 * 
 */
export {

    getReactElementSize
};
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.