প্রোপ পরিবর্তন হলে পুনঃ-রেন্ডার প্রতিক্রিয়া উপাদানটি


90

আমি একটি উপস্থাপক উপাদান থেকে একটি উপস্থাপক উপাদান পৃথক করার চেষ্টা করছি। আমি একটি SitesTableএবং একটি আছে SitesTableContainer। ধারকটি বর্তমান ব্যবহারকারীর উপর ভিত্তি করে উপযুক্ত সাইটগুলি আনার জন্য রিডেক্স ক্রিয়াগুলি ট্রিগার করার জন্য দায়ী।

সমস্যাটি হ'ল বর্তমান ব্যবহারকারীর কন্টেন্টার উপাদানটি প্রাথমিকভাবে রেন্ডার হওয়ার পরে, অ্যাসিনক্রোনাসলি আনা হয়েছে। এর অর্থ হ'ল ধারক উপাদানটি জানে না যে এটির componentDidMountফাংশনে কোডটি পুনরায় কার্যকর করা দরকার যা প্রেরণে ডেটা আপডেট করে SitesTable। আমি মনে করি যে ধারক উপাদানটির কোনও প্রপস (ব্যবহারকারী) পরিবর্তিত হলে আমার পুনরায় রেন্ডার করতে হবে। আমি কীভাবে এটি সঠিকভাবে করব?

class SitesTableContainer extends React.Component {
    static get propTypes() {
      return {
        sites: React.PropTypes.object,
        user: React.PropTypes.object,
        isManager: React.PropTypes.boolean
      }
     }

    componentDidMount() {
      if (this.props.isManager) {
        this.props.dispatch(actions.fetchAllSites())
      } else {
        const currentUserId = this.props.user.get('id')
        this.props.dispatch(actions.fetchUsersSites(currentUserId))
      }  
    }

    render() {
      return <SitesTable sites={this.props.sites}/>
    }
}

function mapStateToProps(state) {
  const user = userUtils.getCurrentUser(state)

  return {
    sites: state.get('sites'),
    user,
    isManager: userUtils.isManager(user)
  }
}

export default connect(mapStateToProps)(SitesTableContainer);

আপনার কিছু অন্যান্য ফাংশন উপলভ্য রয়েছে যেমন কমপিউনডিজআপডেট, বা সম্ভবত আপনি যা খুঁজছেন সেগুলি, কম্পোনেন্ট উইল রিসিপপ্রস্রোপস (নেক্সটপ্রোপস) যদি
প্রপস

যদি সাইটগুলি তার প্রপস পরিবর্তন না করে তবে আপনাকে কেন পুনরায় রেন্ডার করতে হবে?
QoP

@ কিউপি পাঠানো হচ্ছে এমন পদক্ষেপগুলি অ্যাপ্লিকেশন স্টেটের নোডকে componentDidMountপরিবর্তন করবে sites, যা পাস করা হবে SitesTable। সাইটস্টেবলের sitesনোড পরিবর্তন হবে।
ডেভিড

ওহ, আমি পেয়েছি, আমি উত্তর লিখতে যাচ্ছি।
QoP

4
কীভাবে এটি একটি কার্যকরী উপাদানগুলিতে অর্জন করবেন
yaswanthkoneri

উত্তর:


115

আপনার componentDidUpdateপদ্ধতিতে আপনাকে একটি শর্ত যুক্ত করতে হবে ।

উদাহরণটি ব্যবহার fast-deep-equalকরে বস্তুগুলির তুলনা করা।

import equal from 'fast-deep-equal'

...

constructor(){
  this.updateUser = this.updateUser.bind(this);
}  

componentDidMount() {
  this.updateUser();
}

componentDidUpdate(prevProps) {
  if(!equal(this.props.user, prevProps.user)) // Check if it's a new user, you can also use some unique property, like the ID  (this.props.user.id !== prevProps.user.id)
  {
    this.updateUser();
  }
} 

updateUser() {
  if (this.props.isManager) {
    this.props.dispatch(actions.fetchAllSites())
  } else {
    const currentUserId = this.props.user.get('id')
    this.props.dispatch(actions.fetchUsersSites(currentUserId))
  }  
}

হুক ব্যবহার করে (16.8.0+ প্রতিক্রিয়া)

import React, { useEffect } from 'react';

const SitesTableContainer = ({
  user,
  isManager,
  dispatch,
  sites,
}) => {
  useEffect(() => {
    if(isManager) {
      dispatch(actions.fetchAllSites())
    } else {
      const currentUserId = user.get('id')
      dispatch(actions.fetchUsersSites(currentUserId))
    }
  }, [user]); 

  return (
    return <SitesTable sites={sites}/>
  )

}

আপনি যে প্রোপটির সাথে তুলনা করছেন তা যদি কোনও বস্তু বা অ্যারে হয় তবে আপনার useDeepCompareEffectপরিবর্তে ব্যবহার করা উচিত useEffect


মনে রাখবেন যে JSON.stringify কেবলমাত্র এই ধরণের তুলনার জন্যই ব্যবহার করা যেতে পারে, যদি এটি স্থিতিশীল হয় (নির্দিষ্ট করে এটি নির্দিষ্ট নয়), তবে এটি একই ইনপুটগুলির জন্য একই আউটপুট উত্পাদন করে। অপ্রয়োজনীয় পুনরায় লোড এড়াতে আমি ব্যবহারকারীর আইডির বৈশিষ্ট্যগুলির তুলনা, বা প্রপসগুলিতে ইউজারআইডি-এস পাস করার এবং তাদের সাথে তুলনা করার পরামর্শ দিচ্ছি।
লজল্লি কার্ডিনাল

4
অনুগ্রহ করে নোট করুন যে উপাদানটি উইল রিসিপপ্রস লাইফসাইকেল পদ্ধতি অবহেলিত এবং সম্ভবত প্রতিক্রিয়া 17 এ মুছে ফেলা হবে। কম্পোনেন্টডিউডপেট এবং নতুন গেটডেরাইভস্টেটফ্রোমপ্রোপস পদ্ধতিটির সংমিশ্রণটি ব্যবহার করা রি্যাক্ট ডেভেলের প্রস্তাবিত কৌশল। তাদের ব্লগ পোস্টে আরও: reactjs.org/blog/2018/03/27/update-on-async-rendering.html
মাইকেলপল্টরাক

@ কিউপি দ্বিতীয় উদাহরণ, প্রতিক্রিয়া হুক্স সহ, এটি যখনই userপরিবর্তন হবে তখন কি তা আনমাউন্ট এবং পুনঃনির্মাণ হবে ? এটা কত ব্যয়বহুল?
রোবোট্রন

30

ComponentWillReceiveProps()ভবিষ্যতে বাগ এবং অসঙ্গতিগুলির কারণে অবচয় করা হবে। সাজসরঞ্জাম পরিবর্তনের উপর একটি উপাদান পুনরায় রেন্ডারিং জন্য একটি বিকল্প সমাধান ব্যবহার করা ComponentDidUpdate()এবং ShouldComponentUpdate()

ComponentDidUpdate()যখনই উপাদানটি আপডেট হয় এবং যদি ShouldComponentUpdate()সত্যটি ফিরে আসে তখন তাকে বলা হয় (যদি ShouldComponentUpdate()এটি সংজ্ঞায়িত না করা হয় তবে এটি trueডিফল্টরূপে ফিরে আসে )।

shouldComponentUpdate(nextProps){
    return nextProps.changedProp !== this.state.changedProp;
}

componentDidUpdate(props){
    // Desired operations: ex setting state
}

এই একই আচরণটি এর ComponentDidUpdate()ভিতরে শর্তাধীন বিবৃতিটি অন্তর্ভুক্ত করে কেবল পদ্ধতিটি ব্যবহার করেই সম্পন্ন করা যায়।

componentDidUpdate(prevProps){
    if(prevProps.changedProp !== this.props.changedProp){
        this.setState({          
            changedProp: this.props.changedProp
        });
    }
}

যদি কোনও শর্ত ছাড়াই বা ShouldComponentUpdate()উপাদান নির্ধারণ না করে রাষ্ট্র সেট করার চেষ্টা করে তবে তা অসীম পুনরায় রেন্ডার করবে


4
এই উত্তরটি আপভোট করা দরকার (আপাতত কমপক্ষে অন্তত) যেহেতু অবচয় হ'তে চলেছে componentWillReceivePropsএবং ব্যবহারের বিরুদ্ধে প্রস্তাব দেওয়া হচ্ছে।
আনবিস

দ্বিতীয় ফর্ম (উপাদানডিডআপডেটের অভ্যন্তরে শর্তাধীন বিবৃতি) আমার পক্ষে কাজ করে কারণ আমি চাইছি অন্যান্য রাজ্যের পরিবর্তনগুলি এখনও ঘটুক, যেমন একটি ফ্ল্যাশ বার্তা বন্ধ করে দেওয়া।
ছোট মস্তিষ্ক

11

আপনি KEYঅনন্য কী (ডেটার সংমিশ্রণ) ব্যবহার করতে পারেন যা প্রপসের সাথে পরিবর্তিত হয়, এবং সেই উপাদানটি আপডেট প্রপসের সাহায্যে রেন্ডার হবে।


4
componentWillReceiveProps(nextProps) { // your code here}

আমি মনে করি এটি আপনার প্রয়োজন ইভেন্ট। componentWillReceivePropsট্রিগারগুলি যখনই আপনার উপাদানগুলি প্রপসের মাধ্যমে কিছু পান। সেখান থেকে আপনি আপনার চেকিং করতে পারেন তারপরে যা করতে চান তা করুন।


11
componentWillReceiveProps
অবহেলিত

2

আমি আমার এই উত্তরটি একবার দেখার পরামর্শ দিচ্ছি এবং আপনি যা করছেন তার সাথে এটি প্রাসঙ্গিক কিনা তা দেখুন। যদি আমি আপনার আসল সমস্যাটি বুঝতে পারি তবে এটি হ'ল আপনি কেবল আপনার অ্যাসিঙ্ক ক্রিয়াটি সঠিকভাবে ব্যবহার করছেন না এবং রিডুক্স "স্টোর" আপডেট করবেন যা এটি নতুন প্রপসের সাহায্যে স্বয়ংক্রিয়ভাবে আপনার উপাদান আপডেট করবে।

আপনার কোডের এই বিভাগ:

componentDidMount() {
      if (this.props.isManager) {
        this.props.dispatch(actions.fetchAllSites())
      } else {
        const currentUserId = this.props.user.get('id')
        this.props.dispatch(actions.fetchUsersSites(currentUserId))
      }  
    }

কোনও উপাদানটিতে ট্রিগার করা উচিত নয়, এটি আপনার প্রথম অনুরোধটি কার্যকর করার পরে পরিচালনা করা উচিত।

রিডেক্স-থাঙ্ক থেকে এই উদাহরণটি দেখুন :

function makeASandwichWithSecretSauce(forPerson) {

  // Invert control!
  // Return a function that accepts `dispatch` so we can dispatch later.
  // Thunk middleware knows how to turn thunk async actions into actions.

  return function (dispatch) {
    return fetchSecretSauce().then(
      sauce => dispatch(makeASandwich(forPerson, sauce)),
      error => dispatch(apologize('The Sandwich Shop', forPerson, error))
    );
  };
}

অগত্যা আপনাকে রিডেক্স-থাঙ্ক ব্যবহার করতে হবে না, তবে এটি আপনাকে এই জাতীয় পরিস্থিতি সম্পর্কে যুক্তি দেখাতে এবং ম্যাচ করার জন্য কোড লিখতে সহায়তা করবে।


ঠিক আছে, আমি এটি পেয়েছি। তবে আপনি ঠিক কোথায় makeASandwichWithSecretSauce আপনার উপাদানটি প্রেরণ করবেন ?
ডেভিড

আমি আপনাকে একটি প্রাসঙ্গিক উদাহরণের সাথে একটি রেপোতে লিঙ্ক করব, আপনি কি আপনার অ্যাপ্লিকেশনের সাথে প্রতিক্রিয়া-রাউটার ব্যবহার করেন?
টেমবেজার

@ ডেভিডও এই উদাহরণটির লিঙ্কটির প্রশংসা করবে, আমার মূলত একই সমস্যা রয়েছে।
স্যাম ইউজনিওয়াই

0

ব্যবহার করার জন্য একটি বন্ধুত্বপূর্ণ পদ্ধতিটি হ'ল নীচে, প্রপ আপডেটগুলি একবার এটি স্বয়ংক্রিয়ভাবে উপাদানগুলি রেন্ডার করবে:

render {

let textWhenComponentUpdate = this.props.text 

return (
<View>
  <Text>{textWhenComponentUpdate}</Text>
</View>
)

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