প্রতিক্রিয়া হুকগুলিতে কীভাবে `সেটস্টেট` কলব্যাক ব্যবহার করবেন


116

প্রতিক্রিয়া হুক useStateউপাদান উপাদান সেট করার জন্য পরিচয় করিয়ে দেয় । তবে নীচের কোডের মতো কলব্যাক প্রতিস্থাপন করতে আমি কীভাবে হুক ব্যবহার করতে পারি:

setState(
  { name: "Michael" },
  () => console.log(this.state)
);

রাষ্ট্র আপডেট হওয়ার পরে আমি কিছু করতে চাই।

আমি জানি আমি useEffectঅতিরিক্ত জিনিসগুলি করতে ব্যবহার করতে পারি তবে আমাকে রাষ্ট্রের পূর্বের মানটি পরীক্ষা করতে হবে যার জন্য কিছুটা কোড দরকার requires আমি একটি সহজ সমাধান খুঁজছি যা useStateহুকের সাহায্যে ব্যবহার করা যেতে পারে ।


4
শ্রেণীর উপাদানগুলিতে, আমি async ব্যবহার করেছি এবং সেট স্টেটে আপনি একটি কলব্যাক যোগ করার মতো করে একই ফলাফল অর্জনের জন্য অপেক্ষা করছি। দুর্ভাগ্যক্রমে, এটি হুক কাজ করছে না। এমনকি যদি আমি অ্যাসিঙ্ক যোগ করে অপেক্ষা করি তবে প্রতিক্রিয়া রাষ্ট্র আপডেট হওয়ার অপেক্ষায় থাকবে না। হতে পারে UseEffect এটি করার একমাত্র উপায়।
মিং WU

4
@ জাও, আপনি এখনও সঠিক উত্তরটি চিহ্নিত করেন নি। আপনি কি দয়া করে কয়েক সেকেন্ড বাঁচাতে পারবেন
জোহাইব ইজাজ

উত্তর:


126

useEffectএটি অর্জনের জন্য আপনার হুক ব্যবহার করা দরকার ।

const [counter, setCounter] = useState(0);

const doSomething = () => {
  setCounter(123);
}

useEffect(() => {
   console.log('Do something after counter has changed', counter);
}, [counter]);

47
এটি console.logপ্রথম রেন্ডারের পাশাপাশি যে কোনও সময় counterপরিবর্তনের কাজ শুরু করবে। প্রাথমিক মান নির্ধারিত হওয়ার পরে আপনি যদি কেবল রাষ্ট্র আপডেট হওয়ার পরে প্রাথমিক রেন্ডারে না পরে কিছু করতে চান? আমার ধারণা আপনি মানটি পরীক্ষা করতে useEffectপারেন এবং সিদ্ধান্ত নিতে পারেন আপনি যদি কিছু করতে চান তবে। এটি কি সেরা অনুশীলন হিসাবে বিবেচিত হবে?
ড্যারিল ইয়ং

4
useEffectপ্রাথমিক রেন্ডারে চালানো এড়াতে , আপনি একটি কাস্টম useEffectহুক তৈরি করতে পারেন , যা প্রাথমিক রেন্ডারে চালিত হয় না। : এই ধরনের একটি হুক তৈরি করতে হলে, আপনি যদি এই প্রশ্নের চেক আউট করতে পারেন stackoverflow.com/questions/53253940/...

10
এবং ক্ষেত্রে কী হবে, যখন আমি বিভিন্ন সেটস্টেট কলগুলিতে বিভিন্ন কলব্যাক কল করতে চাই, যা একই রাষ্ট্রের মান পরিবর্তন করবে? আপনি উত্তর ভুল, এবং newbies বিভ্রান্ত না করার জন্য সঠিক হিসাবে চিহ্নিত করা উচিত নয়। সত্যটি হ'ল সেট স্টেট তার অন্যতম কঠিন সমস্যাটিকে কলব্যাক করে যখন ক্লাস থেকে হুকগুলিতে স্থানান্তরিত হয় যার একটি পরিষ্কার সমাধান পদ্ধতি নেই method কখনও কখনও আপনি সত্যিকার অর্থে কিছু মান-নির্ভর প্রভাবকে বাড়িয়ে তুলবেন এবং কখনও কখনও এটির জন্য কিছু হ্যাকি পদ্ধতি প্রয়োজন যেমন রেফগুলিতে কিছু ধরণের পতাকা সংরক্ষণ করা।
দিমিত্রি লোবভ

স্পষ্টতই, আজকে আমি সেটকাউন্টারকে কল করতে পারি (মান, কলব্যাক) যাতে কোনও কাজ কার্যকরভাবে এড়ানো অবস্থায় রাষ্ট্র আপডেট হওয়ার পরে কোনও কার্য সম্পাদিত হয়। আমি এটি নিশ্চিত বা নিশ্চিত না যে এটি কোনও পছন্দ বা কোনও বিশেষ সুবিধা benefit
কেন ইঙ্গ্রাম

4
@ কেনগ্রাম আমি কেবল এটি চেষ্টা করেছি এবং এটি খুব নির্দিষ্ট ত্রুটি পেয়েছি:Warning: State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect().
গ্রেগ সাদেটস্কি

22

আপনি যদি পূর্বের অবস্থাটি আপডেট করতে চান তবে আপনি এইভাবে হুক্সে করতে পারেন:

const [count, setCount] = useState(0);


setCount(previousCount => previousCount + 1);

4
আমি setCounterআপনার দ্বারা মনে করিsetCount
মেহেদী দেহঘানি

15

আমার মনে হয়, ব্যবহার useEffectকরা কোনও স্বজ্ঞাত উপায় নয়।

আমি এটির জন্য একটি মোড়ক তৈরি করেছি। এই কাস্টম হুকটিতে আপনি নিজের কলব্যাকটি setStateপ্যারামিটারের পরিবর্তে প্যারামিটারে স্থানান্তর করতে পারেন useState

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

ব্যবহার

const [state, setState] = useStateCallback(1);
setState(2, (n) => {
  console.log(n) // 2
});

ঘোষণা

import { SetStateAction, useCallback, useEffect, useRef, useState } from 'react';

type Callback<T> = (value?: T) => void;
type DispatchWithCallback<T> = (value: T, callback?: Callback<T>) => void;

function useStateCallback<T>(initialState: T | (() => T)): [T, DispatchWithCallback<SetStateAction<T>>] {
  const [state, _setState] = useState(initialState);

  const callbackRef = useRef<Callback<T>>();
  const isFirstCallbackCall = useRef<boolean>(true);

  const setState = useCallback((setStateAction: SetStateAction<T>, callback?: Callback<T>): void => {
    callbackRef.current = callback;
    _setState(setStateAction);
  }, []);

  useEffect(() => {
    if (isFirstCallbackCall.current) {
      isFirstCallbackCall.current = false;
      return;
    }
    callbackRef.current?.(state);
  }, [state]);

  return [state, setState];
}

export default useStateCallback;

খসড়া

যদি পাস করা তীর ফাংশনটি একটি পরিবর্তনশীল বাহ্যিক ফাংশন উল্লেখ করে, তবে এটি রাষ্ট্র আপডেট হওয়ার পরে বর্তমান মান একটি মান নয় capture উপরের ব্যবহারের উদাহরণে, কনসোল.লগ (রাজ্য) 1 টি না 2 টি মুদ্রণ করবে।


4
ধন্যবাদ! শীতল পদ্ধতির একটি নমুনা কোডস্যান্ডবক্স
ValYouW

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

হ্যাঁ, এটি কার্যকরী উপাদানগুলির সাথে আকর্ষণীয় অংশ ...
ValYouW

এখানে পূর্বের রাষ্ট্রীয় মূল্য কীভাবে পাবেন?
অঙ্কন-জেরোব

@ অঙ্কন-জেরোব আমি মনে করি, ব্যবহারের অংশে stateকলব্যাক ডাকার সময় পূর্ববর্তীটি উল্লেখ করছে। তাই না?
এমজে স্টুডিও

14

useEffect, এটি শুধুমাত্র রাষ্ট্রীয় আপডেটগুলিতে আগুন জ্বালিয়ে দেয় :

const [state, setState] = useState({ name: "Michael" })
const isFirstRender = useRef(true)

useEffect(() => {
  if (!isFirstRender.current) {
    console.log(state) // do something after state has updated
  }
}, [state])

useEffect(() => { 
  isFirstRender.current = false // toggle flag after first render/mounting
}, [])

উপরের কলব্যাকটি নকল করবে setStateসেরা এবং প্রাথমিক অবস্থায় আগুন নয় । আপনি এটি থেকে একটি কাস্টম হুক নিষ্কাশন করতে পারেন:

function useEffectUpdate(effect, deps) {
  const isFirstRender = useRef(true) 

  useEffect(() => {
    if (!isFirstRender.current) {
      effect()
    }  
  }, deps) // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    isFirstRender.current = false;
  }, []);
}

// ... Usage inside component
useEffectUpdate(() => { console.log(state) }, [state])

বিকল্প: ক্লাসগুলির মতো কলব্যাক পাওয়ার জন্য useState প্রয়োগ করা যেতে পারেsetState
ford04

0

আপনার প্রশ্নটি খুব বৈধ me আমাকে আপনাকে বলতে দিন যে ইউজএফেক্ট একবার ডিফল্টরূপে চালানো হয় এবং প্রতিবারের পরে নির্ভরতা অ্যারে পরিবর্তিত হয়।

নীচের উদাহরণটি পরীক্ষা করুন ::

import React,{ useEffect, useState } from "react";

const App = () => {
  const [age, setAge] = useState(0);
  const [ageFlag, setAgeFlag] = useState(false);

  const updateAge = ()=>{
    setAgeFlag(false);
    setAge(age+1);
    setAgeFlag(true);
  };

  useEffect(() => {
    if(!ageFlag){
      console.log('effect called without change - by default');
    }
    else{
      console.log('effect called with change ');
    }
  }, [ageFlag,age]);

  return (
    <form>
      <h2>hooks demo effect.....</h2>
      {age}
      <button onClick={updateAge}>Text</button>
    </form>
  );
}

export default App;

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


4
এটি কাজ করবে না। আপনি জানেন না যে আপডেটেজের ভিতরে তিনটি বিবৃতি আসলে কাজ করবে। তিনটিই অ্যাসিঙ্ক। কেবলমাত্র গ্যারান্টিযুক্ত হ'ল প্রথম লাইনটি তৃতীয় পূর্বে চলে (যেহেতু তারা একই রাজ্যে কাজ করে)। আপনি ২ য় লাইন সম্পর্কে কিছুই জানেন না। এই উদাহরণটি এটি দেখার জন্য খুব একইসাথে।
মোহিত সিং

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

4
"আমার প্রকল্পে কাজ করা কোনও ব্যাখ্যা নয়", দস্তাবেজগুলি পড়ুন। এগুলি মোটেই সিঙ্ক্রোনাস নয়। আপনি নিশ্চিত করে বলতে পারবেন না যে আপডেটএজে তিনটি লাইন সেই ক্রমে কাজ করবে। যদি এটি সিঙ্কে থাকে তবে ফ্ল্যাগের কী প্রয়োজন, সেটএজের পরে সরাসরি কনসোল.লগ () লাইনে কল করুন।
মোহিত সিং

"এজফ্ল্যাগ" এর জন্য ইউজারিফ একটি আরও ভাল সমাধান।
ডাঃফ্লিংক

0

setState() উপাদানগুলির স্থিতিতে পরিবর্তনগুলি চিহ্নিত করে এবং প্রতিক্রিয়া জানায় যে এই উপাদানটি এবং তার শিশুদের আপডেট হওয়া অবস্থায় পুনরায় রেন্ডার করা দরকার।

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

setState(
  { name: "Michael" },
  () => console.log(this.state)
);

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

স্পষ্ট পদ্ধতিটি, যা মাথায় আসে তা হ'ল ypu ব্যবহারের সাথে ব্যবহার করতে পারে প্রভাবটি নীচের মত:

const [state, setState] = useState({ name: "Michael" })

useEffect(() => {
  console.log(state) // do something after state has updated
}, [state])

তবে এটি প্রথম রেন্ডারেও আগুন লাগবে, তাই আমরা কোডটি নীচে পরিবর্তন করতে পারি যেখানে আমরা প্রথম রেন্ডার ইভেন্টটি পরীক্ষা করতে পারি এবং রাষ্ট্রীয় রেন্ডার এড়াতে পারি। সুতরাং বাস্তবায়ন নিম্নলিখিত উপায়ে করা যেতে পারে:

প্রথম রেন্ডার সনাক্ত করতে আমরা এখানে ব্যবহারকারীর হুক ব্যবহার করতে পারি।

ব্যবহারের রেফ হুক আমাদের কার্যকরী উপাদানগুলিতে পারস্পরিক পরিবর্তনশীল ভেরিয়েবল তৈরি করতে দেয়। এটি ডিওএম নোডগুলি / প্রতিক্রিয়া উপাদানগুলিতে অ্যাক্সেস করার জন্য এবং পুনরায় রেন্ডারটি ট্রিগার না করে পারস্পরিক পরিবর্তনশীলগুলি সঞ্চয় করার জন্য দরকারী।

const [state, setState] = useState({ name: "Michael" });
const firstTimeRender = useRef(true);

useEffect(() => {
 if (!firstTimeRender.current) {
    console.log(state);
  }
}, [state])

useEffect(() => { 
  firstTimeRender.current = false 
}, [])

0

আমার একটি ব্যবহারের কেস ছিল যেখানে আমি রাজ্যটি সেট হওয়ার পরে কিছু প্যারামের সাথে একটি এপি কল করতে চেয়েছিলাম । আমি এই প্যারামগুলিকে আমার রাজ্য হিসাবে সেট করতে চাইনি তাই আমি একটি কাস্টম হুক তৈরি করেছি এবং এটিই আমার সমাধান

import { useState, useCallback, useRef, useEffect } from 'react';
import _isFunction from 'lodash/isFunction';
import _noop from 'lodash/noop';

export const useStateWithCallback = initialState => {
  const [state, setState] = useState(initialState);
  const callbackRef = useRef(_noop);

  const handleStateChange = useCallback((updatedState, callback) => {
    setState(updatedState);
    if (_isFunction(callback)) callbackRef.current = callback;
  }, []);

  useEffect(() => {
    callbackRef.current();
    callbackRef.current = _noop; // to clear the callback after it is executed
  }, [state]);

  return [state, handleStateChange];
};

-3

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

const [counter, setCounter] = useState(0);

const doSomething = () => {
  const updatedNumber = 123;
  setCounter(updatedNumber);

  // now you can "do something" with updatedNumber and don't have to worry about the async nature of setState!
  console.log(updatedNumber);
}

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