প্রতিক্রিয়া - কীভাবে কোনও ফাংশন উপাদানকে রেন্ডার করতে বাধ্য করা যায়?


99

আমার একটি ফাংশন উপাদান রয়েছে এবং আমি এটি পুনরায় রেন্ডার করতে বাধ্য করতে চাই।

আমি কীভাবে এটি করতে পারি?
যেহেতু কোনও উদাহরণ নেই this, তাই আমি কল করতে পারি না this.forceUpdate()


4
না, একটি রাষ্ট্রবিহীন উপাদানগুলির একটি রাষ্ট্র নেই। পরিবর্তে একটি ক্লাস ব্যবহার করুন
o

4
আপনি কি সত্যই "স্টেটলেস উপাদান " এবং "ক্রিয়ামূলক উপাদান" নয় ?
ক্রিস

4
একটি রাষ্ট্রবিহীন উপাদান আপডেট করার জন্য, প্রপসগুলি পরিবর্তিত হওয়া দরকার।
ছত্রাকসংক্রান্তি

4
প্রপসের পাশে আপনি হুক ইউজস্টেট ব্যবহার করতে পারেন, এবং উপাদানগুলি পরিবর্তন হলে এটি পুনরায় রেন্ডার হবে
হামিদ শোজা

উত্তর:


152

🎉 আপনি এখন, প্রতিক্রিয়া হুক ব্যবহার করে করতে পারেন

প্রতিক্রিয়া হুক ব্যবহার করে, আপনি এখন useState()আপনার ফাংশন উপাদান কল করতে পারেন ।

useState() 2 টি জিনিসের একটি অ্যারে ফিরিয়ে দেবে:

  1. একটি মান, বর্তমান অবস্থার প্রতিনিধিত্ব করে।
  2. এর সেটার। মান আপডেট করতে এটি ব্যবহার করুন।

সেটারের দ্বারা মান আপডেট করা আপনার ফাংশন উপাদানটিকে পুনরায় রেন্ডার করতে বাধ্য করবে ,
ঠিক যেমন forceUpdate:

import React, { useState } from 'react';

//create your forceUpdate hook
function useForceUpdate(){
    const [value, setValue] = useState(0); // integer state
    return () => setValue(value => value + 1); // update the state to force render
}

function MyComponent() {
    // call your hook here
    const forceUpdate = useForceUpdate();
    
    return (
        <div>
            {/*Clicking on the button will force to re-render like force update does */}
            <button onClick={forceUpdate}>
                Click to re-render
            </button>
        </div>
    );
}

আপনি এখানে একটি ডেমো খুঁজে পেতে পারেন

উপরের উপাদানটি একটি কাস্টম হুক ফাংশন ( useForceUpdate) ব্যবহার করে যা প্রতিক্রিয়ার স্টেট হুক ব্যবহার করে useState। এটি উপাদানটির রাষ্ট্রের মান বাড়ায় এবং এভাবে উপাদানটিকে পুনরায় সরবরাহ করতে প্রতিক্রিয়া জানায়।

সম্পাদনা

এই উত্তরের একটি পুরানো সংস্করণে স্নিপেট একটি বুলিয়ান মান ব্যবহার করেছে এবং এটিকে টগল করে forceUpdate()। এখন আমি আমার উত্তরটি সম্পাদনা করেছি, স্নিপেট একটি বুলিয়ান পরিবর্তে একটি সংখ্যা ব্যবহার করে।

কেন? (আপনি আমাকে জিজ্ঞাসা করবে)

কারণ একবার যখন আমার সাথে ঘটেছিল যে আমার forceUpdate()পরে 2 টি পৃথক ঘটনা থেকে দু'বার কল করা হয়েছিল, এবং এভাবে এটি তার মূল অবস্থানে বুলিয়ান মানটির পুনরায় গবেষণা করছিল, এবং উপাদানটি কখনও রেন্ডার হয়নি।

এর কারণ এটির useStateসেটারে ( setValueএখানে) Reactপূর্বের রাজ্যটিকে নতুনের সাথে তুলনা করুন, এবং রাজ্যটি আলাদা হলেই রেন্ডার করুন।


4
কল করতে হুক্স ব্যবহার করার বিষয়ে সেই পৃষ্ঠার কোনও কিছুরই কোনও তথ্য নেই forceUpdate
jdelman

4
আপাতত, আপনি ঠিক বলেছেন এটি আরও ভাল, কারণ, এমনকি শক্ত হুকগুলি এখনও প্রকাশিত হয়নি, আপনি এখনও এটি বিটাতে ব্যবহার করতে পারেন। তবে একবার তাদের ছেড়ে দেওয়া হলে শ্রেণীর উপাদান আরও ভাল হবে এমন কোনও কারণ নেই। হুক ব্যবহার করা কোডকে ক্লাসের উপাদানগুলির চেয়ে আরও পরিষ্কার করে তোলে, যেমন রিঅ্যাক্টনফের নীচের ভিডিওটি দেখায়। যাইহোক, প্রশ্ন যদি এটি সম্ভব হয়। হুকসের কারণে উত্তর এখন "না" থেকে "হ্যাঁ" এ পরিবর্তিত হয়েছে। youtube.com/watch?v=wXLf18DsV-I
Yairopro

4
হাই @ দান্তে স্মিথ "শীর্ষ স্তর" দ্বারা, এর অর্থ হুকগুলি অবশ্যই কোনও শর্ত বা লুপের ভিতর থেকে কল করা উচিত নয়, যেমনটি আপনি বলেছিলেন। তবে আমি আপনাকে বলতে পারি যে আপনি তাদের অন্য ফাংশন থেকে কল করতে পারেন। এবং এর অর্থ একটি কাস্টম হুক তৈরি করা। ড্যান আব্রামভ, যেমন রিএ্যাক্ট
কনফিডে রিয়েক্ট

4
"জোর করে রেন্ডার করতে" কোনও রাষ্ট্রকে টগল করার দরকার নেই। আপনি একটি মিথ্যা ছাপ তৈরি করেন যা প্রতিক্রিয়াটিকে পূর্বের এবং পরবর্তী রাষ্ট্রীয় মানগুলি পুনরায় রেন্ডার করতে হবে কিনা তা সিদ্ধান্ত নিতে "তুলনা" করে। এটি অবশ্যই না।
meandre

4
@ ম্যান্ড্রে হ্যাঁ এটি অবশ্যই তুলনা করে। আমরা useStateহুক সম্পর্কে কথা বলছি , শ্রেণি নয় ' setStateযা প্রকৃতপক্ষে তুলনা করে না (যদি না আপনি উক্ত আপডেট পদ্ধতিটি প্রয়োগ করেন)। আমি পোস্ট করা একই ডেমোটি দেখুন, তবে এর জন্য ব্যবহৃত একটি স্ট্যাটিক মান সহ setState, এটি আবার রেন্ডার হয় না: কোডস্যান্ডবক্স.আইও
ডিটেইনারড-

49

আপডেট প্রতিক্রিয়া v16.8 (16 ফেব্রুয়ারী 2019 রিলিজ)

যেহেতু হুক সহ 16.8 প্রকাশিত হয়েছে প্রতিক্রিয়া , ফাংশন উপাদানগুলিতে এখন অধ্যবসায়ী ধরে রাখার ক্ষমতা রয়েছে state। সেই দক্ষতার সাহায্যে আপনি এখন একটি অনুকরণ করতে পারেন forceUpdate:

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


16.8.0 প্রতিক্রিয়া আগে

না আপনি পারবেন না, স্টেট-লেস ফাংশন উপাদানগুলি কেবল স্বাভাবিক functionsযা প্রত্যাবর্তন করে jsx, আপনি লাইফ চক্র পদ্ধতিগুলি থেকে কোনওরকম অ্যাক্সেস পাবেন না কারণ আপনি এর থেকে প্রসারিত করছেন না React.Component

renderশ্রেণীর উপাদানগুলির পদ্ধতি অংশ হিসাবে ফাংশন-উপাদানটি ভাবেন ।


আপনি করতে পারেন। এতে আসা
প্রপসগুলি

6
এটি পুনরায় রেন্ডার করতে বাধ্য করছে না , এটি কেবলমাত্র একটি সাধারণ রেন্ডার। আপনি যখন জোর করে রেন্ডারিং করতে চান , এটি সাধারণত যখন আপনি যখন রেন্ডার পদ্ধতিটি চালানোর জন্য ডিজাইন করেননি তখন রান করতে চান এমন উদাহরণস্বরূপ, যখন কোনও নতুন propsবা stateপরিবর্তন হয় না। স্টেটলেস উপাদানগুলিতে কোনও ফাংশন না থাকায় আপনি রেন্ডার ফাংশনটিকে জোর করতে পারবেন নাrender । আড়ম্বরহীন উপাদান নেই extends React.Componentতারা যে আয় শুধু সাধারণ ফাংশন হয় jsx
সাগিভ বিজি

"যখন আপনাকে কোনও আপডেট জোর করা দরকার তখন আপনি সম্ভবত কিছু ভুল করছেন" - এর জন্য প্রপসগুলি আমি জানতাম যে এটি ছিল তবে এটি কেবল আমার ব্যবহারের প্রভাবের হুকটি আরও একবার দেখার জন্য আমাকে অনুরোধ করেছিল।
মেথডিশিয়ান

13

অফিসিয়াল প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী ( https://reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate ) এখন এই ভাবে আপনি বিশেষ পরামর্শ দেওয়া হচ্ছে সত্যিই এটা করতে প্রয়োজন:

  const [ignored, forceUpdate] = useReducer(x => x + 1, 0);

  function handleClick() {
    forceUpdate();
  }

আচ্ছা আমি এটি কখনই জানতাম না
চারিথ জয়সঙ্কা

11
এবং আপনি আপনার কোডটি 7 বাইটকে সংক্ষিপ্ত করে তুলতে পারবেন এবং অব্যবহৃত ভেরিয়েবলটি তৈরি করবেন না:const [, forceUpdate] = useReducer(x => x + 1, 0);
কনস্ট্যান্টিন স্মলিয়ানিন

8

আমার প্রতিক্রিয়াশীল কার্যকরী উপাদানগুলি রেন্ডার করার জন্য আমি তৃতীয় পক্ষের লাইব্রেরিটি ব্যবহার-বল-আপডেট বলে ব্যবহার করি। মোহন মত কাজ। আপনার প্রকল্পে প্যাকেজটি আমদানি করুন এবং এটি ব্যবহার করুন।

import useForceUpdate from 'use-force-update';

const MyButton = () => {

  const forceUpdate = useForceUpdate();

  const handleClick = () => {
    alert('I will re-render now.');
    forceUpdate();
  };

  return <button onClick={handleClick} />;
};

4
আপনাকে একটি ক্লিক সংরক্ষণ করতে - অন্যান্য উত্তরে উল্লিখিত হিসাবে useForceUpdateব্যবহার করে useCallback। এই লিবিবটি আপনাকে কয়েকটি কীস্ট্রোক সংরক্ষণ করতে কেবল একটি ইউটিলিটি লাইব।
asyncwait

4
ওহ, আপনাকে ধন্যবাদ. আমি এটা জানতাম না। :)
চরিত জয়সঙ্কা

6

দাবি অস্বীকার: সমস্যাটির উত্তর নেই।

একটি গুরুত্বপূর্ণ নোট এখানে রেখে:

আপনি যদি রাষ্ট্রবিহীন উপাদানকে জোর করে আপডেট করার চেষ্টা করছেন, আপনার নকশায় কিছু ভুল হওয়ার সম্ভাবনা রয়েছে।

নিম্নলিখিত বিষয়গুলি বিবেচনা করুন:

  1. কোনও সন্তানের উপাদানগুলিতে একটি সেটার (সেটস্টেট) পাস করুন যা রাষ্ট্র পরিবর্তন করতে পারে এবং প্যারেন্ট উপাদানটিকে পুনরায় রেন্ডার করতে পারে।
  2. রাষ্ট্র উত্তোলন বিবেচনা করুন
  3. আপনার রেডাক্স স্টোরটিতে সেই স্থিতি স্থাপনের বিষয়টি বিবেচনা করুন, যা সংযুক্ত উপাদানগুলিতে স্বয়ংক্রিয়ভাবে পুনরায় রেন্ডার করতে বাধ্য করতে পারে।

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

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

বাস্তব বিশ্বে এর ব্যবহার রয়েছে। কোনও কিছুরই নিখুঁত হয় না এবং আপনি যদি কখনও সফ্টওয়্যারটি দরজা থেকে সরিয়ে নিতে চান তবে অন্য কেউ যখন এগুলি আপ করবেন তখন কীভাবে জিনিসগুলি ঘটানো যায় তা আপনি আরও ভাল জানেন।
Brain2000

1

হুকগুলি স্পষ্টভাবে ব্যবহার না করেই করা যেতে পারে তবে শর্ত থাকে যে আপনি নিজের উপাদান এবং একটি রাজ্যকে রাজ্যহীন উপাদানটির পিতামাতাদের সাথে যুক্ত করে:

const ParentComponent = props => {
  const [updateNow, setUpdateNow] = useState(true)

  const updateFunc = () => {
    setUpdateNow(!updateNow)
  }

  const MyComponent = props => {
    return (<div> .... </div>)
  }

  const MyButtonComponent = props => {
    return (<div> <input type="button" onClick={props.updateFunc} />.... </div>)
  }

  return (
    <div> 
      <MyComponent updateMe={updateNow} />
      <MyButtonComponent updateFunc={updateFunc}/>
    </div>
  )
}

1

গৃহীত উত্তর ভাল। এটি বুঝতে সহজ করে তুলতে।

উদাহরণ উপাদান:

export default function MyComponent(props) {

    const [updateView, setUpdateView] = useState(0);

    return (
        <>
            <span style={{ display: "none" }}>{updateView}</span>
        </>
    );
}

পুনরায় রেন্ডারিং করার জন্য নীচের কোডটিতে কল করুন:

setUpdateView((updateView) => ++updateView);

-1

এর keyকোনওটিই আমাকে সন্তোষজনক উত্তর দেয় নি তাই শেষ পর্যন্ত আমি যা চেয়েছিলাম তা পেয়েছিলাম প্রোপ, ইউজারিফ এবং কিছু এলোমেলো আইডি জেনারেটরের মতো shortid

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

উদাহরণ কোড:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// ... your JSX functional component, import shortid somewhere

const [render, rerender] = useState(shortid.generate())

const messageList = useRef([
    new Message({id: 1, message: "Hi, let's get started!"})
])

useEffect(()=>{
    await sleep(500)
    messageList.current.push(new Message({id: 1, message: "What's your name?"}))
    // ... more stuff
    // now trigger the update
    rerender(shortid.generate())
}, [])

// only the component with the right render key will update itself, the others will stay as is and won't rerender.
return <div key={render}>{messageList.current}</div> 

আসলে এটি আমাকে রোলিংয়ের সাথে চ্যাট বার্তার মতো কিছু রোল করার অনুমতিও দেয়।

const waitChat = async (ms) => {
    let text = "."
    for (let i = 0; i < ms; i += 200) {
        if (messageList.current[messageList.current.length - 1].id === 100) {
            messageList.current = messageList.current.filter(({id}) => id !== 100)
        }
        messageList.current.push(new Message({
            id: 100,
            message: text
        }))
        if (text.length === 3) {
            text = "."
        } else {
            text += "."
        }
        rerender(shortid.generate())
        await sleep(200)
    }
    if (messageList.current[messageList.current.length - 1].id === 100) {
        messageList.current = messageList.current.filter(({id}) => id !== 100)
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.