রুটের প্যারামিটারগুলি পরিবর্তিত হলে উপাদান পুনঃসমাজ করে না


102

আমি রিএ্যাক্ট-রাউটার ব্যবহার করে একটি প্রতিক্রিয়ার অ্যাপ্লিকেশনটিতে কাজ করছি। আমার একটি প্রকল্প পৃষ্ঠা রয়েছে যার নীচে ইউআরএল রয়েছে:

myapplication.com/project/unique-project-id

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

myapplication.com/project/982378632
myapplication.com/project/782387223
myapplication.com/project/198731289

কম্পোনেন্টডিডমাউন্টটি আবার ট্রিগার করা হয় না তাই ডেটা রিফ্রেশ হয় না। আমার ডেটা রিকোয়েস্টটি ট্রিগার করতে বা এই সমস্যাটি মোকাবিলার জন্য আলাদা কৌশল অবলম্বন করার জন্য আমার আর একটি জীবনচক্রের ইভেন্টটি ব্যবহার করা উচিত?


4
আপনি কি আপনার উপাদানগুলির কোড পোস্ট করতে পারেন?
পিয়ের ক্রুনালেন্সি

উত্তর:


83

লিঙ্কটি যদি কেবল একটি ভিন্ন প্যারামের সাথে একই পথে পরিচালিত হয়, তবে এটি পুনঃনির্মাণ নয়, পরিবর্তে নতুন প্রপস গ্রহণ করবে। সুতরাং, আপনি componentWillReceiveProps(newProps)ফাংশনটি ব্যবহার করতে এবং সন্ধান করতে পারেন newProps.params.projectId

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


4
ধন্যবাদ. আমি কম্পোনেন্ট উইল রিসিপপ্রপস ব্যবহার করে এই কাজটি করতে সক্ষম হয়েছি। আমি এখনও বাস্তবে প্রতিক্রিয়া রাউটার মেগা ডেমো ডেটা প্রবাহ বুঝতে পারি না। আমি কিছু উপাদানগুলিতে স্থির ফ্যাচডেটা সংজ্ঞায়িত দেখতে পাচ্ছি। এই স্ট্যাটিকগুলি কীভাবে রাউটার ক্লায়েন্টের পক্ষ থেকে কল করা হচ্ছে?
Constellates

4
দুর্দান্ত প্রশ্ন। ক্লায়েন্ট.জেএস ফাইল এবং সার্ভার.জেএস ফাইলটি পরীক্ষা করে দেখুন। রাউটারের রানসাইকেল চলাকালীন তারা ফেচডাটা.জেএস ফাইলটি কল করে এবং এটি পাস করে state। এটি প্রথমে কিছুটা বিভ্রান্তিকর তবে পরে আরও পরিষ্কার হয়ে যায়।
ব্র্যাড বি

12
এফওয়াইআই: "উপাদান
উইল রিসিপেটপ্রপস

4
উপাদানযুক্ত উইল রিসিপিজপ্রোপসগুলি অবমূল্যায়িত হওয়ায় আপনার প্রতিক্রিয়া 16 সহ কমপোনেন্টডিড আপডেট ব্যবহার করা উচিত
প্যাটো লোকো

4
এটি কাজ করে তবে এমন সমস্যা রয়েছে যে ডেটা লোড হচ্ছে এমন প্রতিটি উপাদানগুলিতে পুনরায়-রেন্ডারগুলি পরিচালনা করার জন্য আপনার উপাদানটি উইন্ড্রিলিপিসিপ্রোপস () বা উপাদানডিডআপ্পেট () যুক্ত করতে হবে। উদাহরণস্বরূপ এমন কোনও পৃষ্ঠা সম্পর্কে ভাবুন যাতে বেশ কয়েকটি উপাদান রয়েছে যা একই পথের পরামিতির উপর ভিত্তি করে ডেটা লোড করছে।
জুহা সিরাজিলা

102

রুট পরিবর্তিত হওয়ার সময় আপনার যদি কোনও উপাদান পুনঃসমাউন্টের প্রয়োজন হয় তবে আপনি আপনার উপাদানটির কী বৈশিষ্ট্যটির (কীটি আপনার পথ / পথের সাথে সম্পর্কিত) একটি অনন্য কী পাস করতে পারেন। সুতরাং যতবার রুট পরিবর্তন হবে ততবার কীটিও পরিবর্তিত হবে যা প্রতিক্রিয়ার উপাদানটিকে আনমাউন্ট / পুনঃনির্মাণে ট্রিগার করে। আমি এই উত্তরটি থেকে ধারণা পেয়েছি


4
উজ্জ্বল! এই সহজ এবং মার্জিত উত্তরের জন্য আপনাকে ধন্যবাদ
Z_z_Z

শুধু জিজ্ঞাসা করছেন, এটি কি অ্যাপটির কার্যকারিতা প্রভাবিত করবে না?
আল্পিত আনন্দ

4
@ আলপিটান এবং এটি একটি বিস্তৃত প্রশ্ন। পুনরায় মাউন্টিং অবশ্যই পুনরায় রেন্ডারিংয়ের চেয়ে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে বেড়ে যায় যেহেতু এটি আরও জীবনচক্র পদ্ধতিগুলি ট্রিগার করে। এখানে আমি কেবল জবাব দিচ্ছি যে রুট পরিবর্তিত হলে কীভাবে পুনঃনির্মাণ হবে।
ওয়েই

কিন্তু এর কি বিশাল প্রভাব নেই? আপনার পরামর্শ কী আমরা এটিকে বেশি প্রভাব ছাড়াই নিরাপদে ব্যবহার করতে পারি?
অলিপিত আনন্দ

4
@ অ্যালপিটান এবং আপনার প্রশ্নটি খুব বিস্তৃত এবং অ্যাপ্লিকেশন নির্দিষ্ট। কিছু অ্যাপ্লিকেশনগুলির জন্য, হ্যাঁ, এটি একটি পারফরম্যান্স হিট হবে, এক্ষেত্রে আপনার নিজের প্রপসগুলি পরিবর্তন করা উচিত এবং কেবলমাত্র আপডেট হওয়া উচিত এমন উপাদানগুলি আপডেট করা উচিত। যদিও বেশিরভাগের জন্য,
ক্রিস

86

এখানে আমার উত্তর, উপরের কিছু মত কিন্তু কোড সহ।

<Route path="/page/:pageid" render={(props) => (
  <Page key={props.match.params.pageid} {...props} />)
} />

4
এখানে কীটি সর্বাধিক ভূমিকা পালন করে, কারণ কোনও প্রোফাইল পৃষ্ঠায় আপনার লিঙ্কটি রয়েছে এমন চিত্রটি ক্লিক করার পরে এটি কেবল একই পথে ফিরে যেতে পারে তবে বিভিন্ন পরামিতি সহ, উপাদানটি আপডেট হয় না, কারণ প্রতিক্রিয়া কোনও পার্থক্য খুঁজে পায় না, কারণ পুরানো ফলাফলের তুলনা করার জন্য অবশ্যই অবশ্যই একটি কেই থাকতে হবে
জর্জি পিভ

15

আপনার পরিষ্কার হতে হবে, রুট পরিবর্তনের ফলে কোনও পৃষ্ঠা রিফ্রেশ হবে না, আপনাকে নিজেই এটি পরিচালনা করতে হবে।

import theThingsYouNeed from './whereYouFindThem'

export default class Project extends React.Component {

    componentWillMount() {

        this.state = {
            id: this.props.router.params.id
        }

        // fire action to update redux project store
        this.props.dispatch(fetchProject(this.props.router.params.id))
    }

    componentDidUpdate(prevProps, prevState) {
         /**
         * this is the initial render
         * without a previous prop change
         */
        if(prevProps == undefined) {
            return false
        }

        /**
         * new Project in town ?
         */
        if (this.state.id != this.props.router.params.id) {
           this.props.dispatch(fetchProject(this.props.router.params.id))
           this.setState({id: this.props.router.params.id})
        }

    }

    render() { <Project .../> }
}

ধন্যবাদ, এই সমাধানটি আমার পক্ষে কাজ করে। তবে আমার এসলিন্ট সেটিংটি এই সম্পর্কে অভিযোগ করছে: github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/… এ সম্পর্কে আপনার কী ধারণা?
কোনেকোয়ায়

হ্যাঁ যে আসলে না করাই ভাল অনুশীলন, দুঃখিত যে সম্পর্কে, "fetchProject" ডিসপ্যাচিং পরে আপনার হ্রাসকারক কোন পথে আপনার সাজসরঞ্জাম আপডেট হবে, আমি শুধু এই স্থানে redux নির্বাণ ছাড়া ব্যবহার করা হয়ে আমার বক্তব্য প্রকাশ করতে
chickenchilli

হাই চিকনচিল্লি, আমি আসলে এখনও এতে আটকে আছি ... আপনার কাছে অন্য পরামর্শ বা প্রস্তাবিত টিউটোরিয়াল রয়েছে? অথবা আমি আপাতত আপনার সমাধানটি আটকে রাখব। আপনার সাহায্যের জন্য ধন্যবাদ!
konekoya

14

যদি তোমার থাকে:

<Route
   render={(props) => <Component {...props} />}
   path="/project/:projectId/"
/>

হুক ব্যবহার করে ১.8.৮ এবং তারও বেশি প্রতিক্রিয়াতে আপনি এটি করতে পারেন:

import React, { useEffect } from "react";
const Component = (props) => {
  useEffect(() => {
    props.fetchResource();
  }, [props.match.params.projectId]);

  return (<div>Layout</div>);
}
export default Component;

সেখানে fetchResourceযখনই props.match.params.idপরিবর্তন ঘটে আপনি কেবল নতুন কলটি চালু করছেন ।


4
এটি দেওয়া আরও উত্তম উত্তর যে আরও বেশিরভাগ উত্তর এখন componentWillReceiveProps
অবনমিত

9

@Wei করে উত্তর উপর ভিত্তি করে, @ Breakpoint25 এবং @PaulusLimma আমি এই প্রতিস্থাপন উপাদান তৈরি <Route>। এটি ইউআরএল পরিবর্তিত হয়ে পৃষ্ঠার সমস্ত উপাদানকে পুনরায় রেন্ডার করে নয়, পৃষ্ঠার সমস্ত উপাদান তৈরি এবং পুনরায় মাউন্ট করার জন্য বাধ্য করে যখন পৃষ্ঠাটি পুনঃসারণ করবে। সমস্ত componentDidMount()এবং সমস্ত অন্যান্য স্টার্টআপ হুকগুলি ইউআরএল পরিবর্তনেও কার্যকর করা হয়।

keyইউআরএল পরিবর্তিত হলে উপাদানগুলির বৈশিষ্ট্য পরিবর্তন করার ধারণাটি আসে এবং এই উপাদানটি পুনরায় মাউন্ট করার জন্য প্রতিক্রিয়া দেখায়।

আপনি এটির জন্য ড্রপ-ইন প্রতিস্থাপন হিসাবে ব্যবহার করতে পারেন <Route>, উদাহরণস্বরূপ:

<Router>
  <Switch>
    <RemountingRoute path="/item/:id" exact={true} component={ItemPage} />
    <RemountingRoute path="/stuff/:id" exact={true} component={StuffPage} />
  </Switch>
</Router>

<RemountingRoute>কম্পোনেন্ট ভালো সংজ্ঞায়িত করা হয়:

export const RemountingRoute = (props) => {
  const {component, ...other} = props
  const Component = component
  return (
    <Route {...other} render={p => <Component key={p.location.pathname + p.location.search}
                                              history={p.history}
                                              location={p.location}
                                              match={p.match} />}
    />)
}

RemountingRoute.propsType = {
  component: PropTypes.object.isRequired
}

এটি প্রতিক্রিয়া-রাউটার ৪.৩ দিয়ে পরীক্ষা করা হয়েছে।


5

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

const MainContent = ({location}) => (
    <Switch>
        <Route exact path='/projects' component={Tasks} key={location.pathname}/>
        <Route exact path='/tasks' component={Projects} key={location.pathname}/>
    </Switch>
);

export default withRouter(MainContent)

5

এইভাবে আমি সমস্যার সমাধান করেছি:

এই পদ্ধতিটি এপিআই থেকে স্বতন্ত্র আইটেম পায়:

loadConstruction( id ) {
    axios.get('/construction/' + id)
      .then( construction => {
        this.setState({ construction: construction.data })
      })
      .catch( error => {
        console.log('error: ', error);
      })
  }

আমি উপাদানটি ডিডমাউন্ট থেকে এই পদ্ধতিটি কল করি, এই পদ্ধতিটি কেবল একবার ডাকা হবে, যখন আমি এই রুটটি প্রথমবার লোড করব:

componentDidMount() {   
    const id = this.props.match.params.id;
    this.loadConstruction( id )
  }

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

componentWillReceiveProps(nextProps) {
    if (nextProps.match.params.id !== this.props.match.params.id) {
      const id = nextProps.match.params.id
      this.loadConstruction( id );
    }
  }

এটি কাজ করে তবে এমন সমস্যা রয়েছে যে ডেটা লোড হচ্ছে এমন প্রতিটি উপাদানগুলিতে পুনরায়-রেন্ডারগুলি পরিচালনা করার জন্য আপনাকে উপাদানবিট্রিলিপিটপ্রোপস () যুক্ত করতে হবে need
জুহা সিরাজিলা

কম্পোনেন্টডিডআপেট (অ্যাডপ্রপ্রপস) ব্যবহার করুন। উপাদানWillUpdate () উপাদানউইলপ্রিয়সপ্রোপস () হ্রাস করা হয়েছে।
মিরেক মিশালাক

0

আপনি ক্লাস কম্পোনেন্ট ব্যবহার করে থাকেন, আপনি ব্যবহার করতে পারেন componentDidUpdate

componentDidMount() {
    const { projectId } = this.props.match.params
    this.GetProject(id); // Get the project when Component gets Mounted
 }

componentDidUpdate(prevProps, prevState) {
    const { projectId } = this.props.match.params

    if (prevState.projetct) { //Ensuring This is not the first call to the server
      if(projectId !== prevProps.match.params.projectId ) {
        this.GetProject(projectId); // Get the new Project when project id Change on Url
      }
    }
 }

কম্পোনেন্টডিডআপেটটি এখন হ্রাস করা হয়েছে, আপনি যদি কিছু বিকল্প প্রস্তাবও দিতে পারেন তবে এটি ভাল হবে।
সাহিল

আপনি কি এ ব্যাপারে নিশ্চিত? কম্পোনেন্টডিডআপডেটটি আসন্ন সংস্করণে অবহেলা করা যাচ্ছে না এবং আপনি কি কোনও লিঙ্ক সংযুক্ত করতে পারবেন? ফাংশনগুলি নিম্নরূপে অবহিত করা হবে: উপাদানউইলমাউন্ট - ইউএনএসএফ_কম্পোনেন্টস উইলমাউন্ট উপাদান উইল রিসিপপ্রপস
অ্যাঞ্জেল মাস

0

আপনি প্রদত্ত পদ্ধতিটি ব্যবহার করতে পারেন:

useEffect(() => {
  // fetch something
}, [props.match.params.id])

রুট পরিবর্তনের পরে যখন উপাদানটি পুনরায় সরবরাহের গ্যারান্টিযুক্ত তখন আপনি নির্ভরতা হিসাবে প্রপসগুলি পাস করতে পারেন

ক্যান্ট সি ডড্ডস অনুসারে আপনি যা সন্ধান করছেন তা পরিচালনা করার পক্ষে সবচেয়ে ভাল উপায় নয় তবে আপনি কী ঘটতে চান তা আরও বিবেচনা করুন।


-3

react-router ভাঙ্গা কারণ এটি অবশ্যই কোনও অবস্থানের পরিবর্তনের উপাদানগুলিকে পুনরায় গণনা করতে হবে।

যদিও আমি এই বাগের জন্য একটি সমাধান খুঁজে পেয়েছি:

https://github.com/ReactTraining/react-router/issues/1982#issuecomment-275346314

সংক্ষেপে (সম্পূর্ণ তথ্যের জন্য উপরের লিঙ্কটি দেখুন)

<Router createElement={ (component, props) =>
{
  const { location } = props
  const key = `${location.pathname}${location.search}`
  props = { ...props, key }
  return React.createElement(component, props)
} }/>

এটি কোনও ইউআরএল পরিবর্তনে এটি পুনঃনির্মাণ করবে

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