উপাদানস্ট্রিডআপ্টেটের ভিতরে সেটস্টেট ()


131

আমি একটি স্ক্রিপ্ট লিখছি যা স্ক্রিনের ড্রপডাউন এবং ইনপুটের অবস্থানের উপর নির্ভর করে ইনপুটটির নীচে বা উপরে ড্রপডাউন সরায়। এছাড়াও আমি এর দিকনির্দেশ অনুসারে ড্রপডাউনতে মডিফায়ার সেট করতে চাই। কিন্তু ব্যবহার করছিsetState তৈরির ভিতরেcomponentDidUpdate করে অসীম লুপ তৈরি হয় (যা সুস্পষ্ট)

আমি ব্যবহার করার একটি সমাধান খুঁজে পেয়েছি getDOMNodeক্লাস নামটি সরাসরি ড্রপডাউনটিতে এবং সেট করার তবে আমি মনে করি যে প্রতিক্রিয়া সরঞ্জামগুলি ব্যবহার করে এর চেয়ে আরও ভাল সমাধান হওয়া উচিত। কেউ কি আমাকে সাহায্য করতে পারেন?

এখানে getDOMNodeকোডিংয়ের একটি অংশ রয়েছে (কোডটি সহজ করার জন্য আইআইএল কিছুটা অবহেলিত অবস্থানের যুক্তি)

let SearchDropdown = React.createClass({
    componentDidUpdate(params) {
        let el = this.getDOMNode();
        el.classList.remove('dropDown-top');
        if(needToMoveOnTop(el)) {
            el.top = newTopValue;
            el.right = newRightValue;
            el.classList.add('dropDown-top');
        }
    },
    render() {
        let dataFeed = this.props.dataFeed;
        return (
            <DropDown >
                {dataFeed.map((data, i) => {
                    return (<DropDownRow key={response.symbol} data={data}/>);
                })}
            </DropDown>
        );
    }
});

এবং এখানে সেটসেট সহ কোড (যা একটি অসীম লুপ তৈরি করে)

let SearchDropdown = React.createClass({
    getInitialState() {
        return {
            top: false
        };
    },
    componentDidUpdate(params) {
        let el = this.getDOMNode();
        if (this.state.top) {
           this.setState({top: false});
        }
        if(needToMoveOnTop(el)) {
            el.top = newTopValue;
            el.right = newRightValue;
            if (!this.state.top) {
              this.setState({top: true});
           }
        }
    },
    render() {
        let dataFeed = this.props.dataFeed;
        let class = cx({'dropDown-top' : this.state.top});
        return (
            <DropDown className={class} >
                {dataFeed.map((data, i) => {
                    return (<DropDownRow key={response.symbol} data={data}/>);
                })}
            </DropDown>
        );
    }
});

9
আমি মনে করি যে এখানে কৌশলটি সর্বদা পুনরায় রেন্ডারকে ট্রিগার setStateকরবে । একাধিকবার চেক করা এবং কল করার পরিবর্তে , আপনি কীভাবে স্থানীয় ভেরিয়েবলে থাকতে চান তা অনুসরণ করুন, তারপরে একবার কল শেষে আপনার স্থানীয় ভেরিয়েবলটি মেলে না । এখনই যেমন দাঁড়িয়েছে, তত্ক্ষণাত্ প্রথম পুনর্বার সরবরাহের পরে আপনি পুনরায় সেট করুন যা আপনাকে অসীম লুপে ফেলে। state.topsetStatestate.topcomponentDidUpdatesetStatestate.topstate.top
র্যান্ডি মরিস

2
এর দুটি ভিন্ন বাস্তবায়নের দেখুন componentDidUpdateমধ্যে এই বেহালার
র্যান্ডি মরিস

ধুর! ছাই! স্থানীয় ভেরিয়েবল পুরো সমস্যাটি সমাধান করে, মাইসেফের দ্বারা আমি এটি কীভাবে আবিষ্কার করতে পারি নি! ধন্যবাদ!
কাতেরিনা পাভেলঙ্কো

1
আমি মনে করি আপনার নীচের উত্তরটি গ্রহণ করা উচিত। আপনি যদি এটি আবার পড়েন তবে আমি মনে করি আপনি এটি প্রাথমিক প্রশ্নের যথেষ্ট উত্তর দেবেন does
র‌্যান্ডি মরিস

কেন কেউ এই অবস্থার মধ্যে স্থানান্তরিত করার পরামর্শ দেয়নি componentShouldUpdate?
প্যাট্রিক রবার্টস

উত্তর:


116

আপনি setStateভিতরে ব্যবহার করতে পারেন componentDidUpdate। সমস্যাটি হ'ল কোনওভাবেই আপনি একটি অসীম লুপ তৈরি করছেন কারণ কোনও ব্রেকের শর্ত নেই।

একবার উপাদানটি রেন্ডার হয়ে গেলে আপনার ব্রাউজারের সরবরাহ করা মানগুলির প্রয়োজনের ভিত্তিতে, আমি মনে করি ব্যবহার সম্পর্কে আপনার দৃষ্টিভঙ্গি componentDidUpdateসঠিক, এটির অবস্থাটিকে আরও ভাল পরিচালনা করা দরকার যা ট্রিগারকে কার্যকর করে setState


4
'ব্রেক কন্ডিশন' বলতে কী বোঝ? রাষ্ট্রটি ইতিমধ্যে সেট করা আছে এবং এটি পুনরায় সেট করা হচ্ছে না তা চেক করছে?
কাতেরিনা পাভেলঙ্কো

আমি এর সাথে একমত, আমার একমাত্র অতিরিক্ত মন্তব্যটি হ'ল ক্লাস যুক্ত করা / অপসারণ সম্ভবত অপ্রয়োজনীয় componentDidUpdateএবং renderপরিবর্তে প্রয়োজন অনুসারে কেবল যুক্ত করা যেতে পারে ।
র্যান্ডি মরিস

কিন্তু ক্লাস যুক্ত / অপসারণ ড্রপডাউন অবস্থানের উপর নির্ভর করে যা উপাদানডিডআপেডে চেক ইন করা আছে, আপনি এটি দুটিবার পরীক্ষা করার পরামর্শ দিচ্ছেন? এবং আমি যেমন বুঝতে পেরেছি, কম্পোনেন্টডিডআপটিকে আফটার রেন্ডার () বলা হয়, সুতরাং রেন্ডারে ক্লাস যুক্ত করা / অপসারণ করা অকেজো ()
কাতেরিনা পাভলঙ্কো

আমি আমার কোডটি সেটেটেট দিয়ে যুক্ত করেছি, আপনি কি এটি পরীক্ষা করে আমার ভুলের দিকে লক্ষ্য রাখতে পারেন? বা আমাকে এমন কিছু উদাহরণ দেখান যা লুপ তৈরি করবে না
কাতেরিনা পাভলেঙ্কো

2
উপাদানডিডিউপেট (প্রিপপ্রোপস, প্রিপস্টেট) {যদি (prevState.x! == this.state.x) {// কিছু করুন}}
অশোক আর

68

componentDidUpdateস্বাক্ষর হয় void::componentDidUpdate(previousProps, previousState)। এটির সাহায্যে আপনি কোন প্রপস / রাজ্য নোংরা তা পরীক্ষা করতে সক্ষম হবেন এবং setStateসেই অনুযায়ী কল করুন ।

উদাহরণ:

componentDidUpdate(previousProps, previousState) {
    if (previousProps.data !== this.props.data) {
        this.setState({/*....*/})
    }
}

componentDidMountকোন যুক্তি নেই, এবং কেবল যখন উপাদান তৈরি করা হয় তখন ডাকা হয়, তাই বর্ণিত উদ্দেশ্যে ব্যবহার করা যাবে না।
জুলাই

@ জুলস ধন্যবাদ! আমি componentDidMountলিখতাম, তাই আমি যখন উত্তরটি লিখি তখন বিখ্যাত নামটি ক্যাসকেড করা হয়েছিল 😮 আবারও, ধন্যবাদ ও দুর্দান্ত!
আবদনূর টুমি

componentDidUpdate(prevProps, prevState) { if ( prevState.x!== this.state.x) { //Do Something } }
অশোক আর

আমি আপনার উদ্বেগ @ আশোকআর জানি। আপনি আরগের নামটি কমিয়ে দিন। তবে "পূর্ব" এর অর্থ পূর্ববর্তী নয় প্রতিরোধ করা সম্ভব .. এইচএইচএইচ। .কিডিং :)
আবদেনর টুমি

58

যদি আপনি ব্যবহার setStateভিতরে componentDidUpdateএটা উপাদান আপডেট একটি কলে ফলে componentDidUpdateযা পরবর্তীতে কল setStateআবার অসীম লুপ ফলে। আপনার শর্তাধীনভাবে কল করা উচিত setStateএবং কলটি লঙ্ঘনকারী শর্তটি শেষ পর্যন্ত ঘটে তা নিশ্চিত করা উচিত :

componentDidUpdate: function() {
    if (condition) {
        this.setState({..})
    } else {
        //do something else
    }
}

আপনি যদি কেবলমাত্র উপাদানটিকে প্রপস প্রেরণ করেই হালনাগাদ করছেন (এটি সেটস্টেট দ্বারা আপডেট করা হচ্ছে না, কম্পোনেন্টডিডআপের অভ্যন্তরের ক্ষেত্রে বাদে), আপনি তার পরিবর্তে setStateভিতরে কল করতে পারেন ।componentWillReceivePropscomponentDidUpdate


2
পুরানো প্রশ্ন তবে উপাদানবিহীনগ্রিপপ্রসেস অবমূল্যায়ন করা হয়েছে এবং উপাদানবিহীনরসিভিউপ্রোপগুলি ব্যবহার করা উচিত। আপনি এই পদ্ধতির অভ্যন্তরে সেটস্টেট করতে পারবেন না।
ব্রুকস ডুবুইস

আপনি বলতে চাচ্ছেন getDerivedStateFromProps
adi518

5

এই উদাহরণটি আপনাকে প্রতিক্রিয়াশীল জীবনচক্র হুক বুঝতে সাহায্য করবে ।

আপনি পদ্ধতিতে পারেন setStateএবং প্রপস পরিবর্তনের পরে পদ্ধতিটি ট্রিগার করতে পারেন ।getDerivedStateFromPropsstaticcomponentDidUpdate

ইন componentDidUpdateআপনি পাবেন 3 য় PARAM যা থেকে ফেরৎ getSnapshotBeforeUpdate

আপনি এই কোডস্যান্ডবক্স লিঙ্কটি চেক করতে পারেন

// Child component
class Child extends React.Component {
  // First thing called when component loaded
  constructor(props) {
    console.log("constructor");
    super(props);
    this.state = {
      value: this.props.value,
      color: "green"
    };
  }

  // static method
  // dont have access of 'this'
  // return object will update the state
  static getDerivedStateFromProps(props, state) {
    console.log("getDerivedStateFromProps");
    return {
      value: props.value,
      color: props.value % 2 === 0 ? "green" : "red"
    };
  }

  // skip render if return false
  shouldComponentUpdate(nextProps, nextState) {
    console.log("shouldComponentUpdate");
    // return nextState.color !== this.state.color;
    return true;
  }

  // In between before real DOM updates (pre-commit)
  // has access of 'this'
  // return object will be captured in componentDidUpdate
  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log("getSnapshotBeforeUpdate");
    return { oldValue: prevState.value };
  }

  // Calls after component updated
  // has access of previous state and props with snapshot
  // Can call methods here
  // setState inside this will cause infinite loop
  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log("componentDidUpdate: ", prevProps, prevState, snapshot);
  }

  static getDerivedStateFromError(error) {
    console.log("getDerivedStateFromError");
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    console.log("componentDidCatch: ", error, info);
  }

  // After component mount
  // Good place to start AJAX call and initial state
  componentDidMount() {
    console.log("componentDidMount");
    this.makeAjaxCall();
  }

  makeAjaxCall() {
    console.log("makeAjaxCall");
  }

  onClick() {
    console.log("state: ", this.state);
  }

  render() {
    return (
      <div style={{ border: "1px solid red", padding: "0px 10px 10px 10px" }}>
        <p style={{ color: this.state.color }}>Color: {this.state.color}</p>
        <button onClick={() => this.onClick()}>{this.props.value}</button>
      </div>
    );
  }
}

// Parent component
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: 1 };

    this.tick = () => {
      this.setState({
        date: new Date(),
        value: this.state.value + 1
      });
    };
  }

  componentDidMount() {
    setTimeout(this.tick, 2000);
  }

  render() {
    return (
      <div style={{ border: "1px solid blue", padding: "0px 10px 10px 10px" }}>
        <p>Parent</p>
        <Child value={this.state.value} />
      </div>
    );
  }
}

function App() {
  return (
    <React.Fragment>
      <Parent />
    </React.Fragment>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


2

আমি বলব যে রাজ্যের ইতিমধ্যে আপনি সেট করার চেষ্টা করছেন একই মান আছে কিনা তা পরীক্ষা করে দেখার দরকার। যদি এটি একই হয় তবে একই মানের জন্য আবার রাষ্ট্র নির্ধারণ করার কোনও মানে নেই।

আপনার রাজ্যটি এটির মতো করে সেট করা নিশ্চিত করুন:

let top = newValue /*true or false*/
if(top !== this.state.top){
    this.setState({top});
}

-1

আমার একইরকম সমস্যা হয়েছিল যেখানে আমাকে টুলটিপটি কেন্দ্র করতে হবে। উপাদানডিডআপডেটে সেটস্টেটের প্রতিক্রিয়া আমাকে অসীম লুপে ফেলেছে, আমি এটি কাজ করার শর্ত চেষ্টা করেছি। কিন্তু আমি রেফ কলব্যাক ব্যবহার করে আমাকে সহজ এবং পরিষ্কার সমাধান পেয়েছি, আপনি রেফ কলব্যাকের জন্য যদি ইনলাইন ফাংশন ব্যবহার করেন তবে প্রতিটি উপাদান আপডেটের জন্য নাল সমস্যার মুখোমুখি হবেন। সুতরাং রেফার কলব্যাকে ফাংশন রেফারেন্স ব্যবহার করুন এবং সেখানে রাষ্ট্র সেট করুন, যা পুনরায় রেন্ডার শুরু করবে

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