সেটস্টেট তাত্ক্ষণিকভাবে রাষ্ট্র আপডেট করে না


111

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

import React from 'react';

import Grid from 'react-bootstrap/lib/Grid';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';

import BoardAddModal from 'components/board/BoardAddModal.jsx';

import style from 'styles/boarditem.css';

class BoardAdd extends React.Component {

    constructor(props){
        super(props);

        this.state = {
            boardAddModalShow: false
        }

        this.openAddBoardModal = this.openAddBoardModal.bind(this);
    }
    openAddBoardModal(){
        this.setState({ boardAddModalShow: true });
// After setting a new state it still return a false value
        console.log(this.state.boardAddModalShow);

    }

    render() {

        return (
            <Col lg={3}>
                <a href="javascript:;" className={style.boardItemAdd} onClick={this.openAddBoardModal}>
                    <div className={[style.boardItemContainer,style.boardItemGray].join(' ')}>
                        Create New Board
                    </div>
                </a>



            </Col>
        )
    }
}

export default BoardAdd

4
এই প্রশ্নের উপর আপনি যে উত্তরটি গ্রহণ করেছেন তা কোনও অর্থহীন নয়। setStateকোন প্রতিশ্রুতি ফিরিয়ে দেয় না যদি এটি কাজ করে তবে এটি কাজ করেছিল কারণ awaitফাংশনে একটি অ্যাসিঙ্ক "টিক" প্রবর্তন করে এবং এটি ঘটেছিল যে স্টেট আপডেটটি সেই টিকের সময় প্রক্রিয়াজাত হয়েছিল। এটির নিশ্চয়তা নেই। যেমন এই জবাবটি বলেছে, আপনার সমাপ্তি কলব্যাকটি ব্যবহার করা দরকার (রাষ্ট্র আপডেট হওয়ার পরে যদি আপনাকে সত্যিই কিছু করা দরকার যা অস্বাভাবিক; সাধারণত, আপনি কেবল পুনরায় রেন্ডার করতে চান, যা স্বয়ংক্রিয়ভাবে ঘটে)
টিজে ক্রাউডার

আপনি যদি বর্তমানে গৃহীত উত্তরগুলি অ-স্বীকার করেন বা সঠিক উত্তর গ্রহণ করেন তবে ভাল হবে, কারণ এটি তখন আরও অনেক প্রশ্নের নকল হিসাবে ব্যবহার করা যেতে পারে। শীর্ষে একটি ভুল উত্তর থাকা বিভ্রান্তিকর।
ছেলে ছদ্মবেশী

উত্তর:


13

এই কলব্যাকটি সত্যিই অগোছালো। পরিবর্তে কেবল অ্যাসিঙ্ক অপেক্ষা করতে ব্যবহার করুন:

async openAddBoardModal(){
    await this.setState({ boardAddModalShow: true });
    console.log(this.state.boardAddModalShow);
}

29
ওটা কোন অর্থ প্রকাশ করে না. প্রতিক্রিয়া setStateএকটি প্রতিশ্রুতি ফিরে না।
টিজে ক্রাউডার

17
@ টিজে ক্রাউডার ঠিক আছে। setStateকোনও প্রতিশ্রুতি ফিরিয়ে দেয় না, তাই এটি অপেক্ষা করা উচিত নয়। এটি বলেছিল, আমি মনে করি এটি আমি কিছু লোকের জন্য কেন কাজ করছি তা দেখতে পাচ্ছি, কারণ অপেক্ষার ফলে বাকী ফাংশনের আগে কল স্ট্যাকের উপর সেটস্টেটের অভ্যন্তরীণ কাজগুলি রাখে, তাই এটি প্রথমে প্রক্রিয়াজাত হয় এবং এভাবেই মনে হয় রাজ্যটি হয়েছে সেট। যদি সেটস্টেটের কোনও নতুন অ্যাসিনক্রোনাস কল থাকে বা প্রয়োগ করে, এই উত্তরটি ব্যর্থ হবে this এই ফাংশনটি সঠিকভাবে প্রয়োগ করতে, আপনি এটি ব্যবহার করতে পারেন:await new Promise(resolve => this.setState({ boardAddModalShow: true }, () => resolve()))
মাইক রিচার্ডস

কিভাবে async this.setState({})আমার সমস্যা সমাধান? আমাদের ওয়ার্কিং কোড ছিল, আরও কিছু বিকাশ হয়েছে তবে অ্যাপ্লিকেশনটির অংশটি কিছুই পরিবর্তন করেনি। সেটস্টেটে কেবলমাত্র দুটি বস্তুর মধ্যে একটি আপডেট হয়ে যাচ্ছিল, এটি অ্যাসিঙ্ককে কার্যকারিতা ফিরিয়ে দিয়েছে এবং এখন উভয় বস্তু সঠিকভাবে আপডেট হচ্ছে। আমার কী ধারণা ছিল না যে এই দোষটি কী ছিল।
ওন্দেজ এভিক

আমি এই প্রশ্নটি পেয়েছি, তবে এই সমাধানটি আমার পক্ষে কার্যকর হয়নি, আমি এখনও আমার সমস্যাটি সমাধান করি নি তবে আমি এখানে একটি ভাল পঠন পেয়েছি: ozmoroz.com/2018/11/why-my-setstate-doesnt-work
carmolim

151

আপনার রাজ্যের পরিবর্তন করতে কিছুটা সময় প্রয়োজন, এবং যেহেতু console.log(this.state.boardAddModalShow)রাষ্ট্রের পরিবর্তনের আগে তা কার্যকর করা হয়, আপনি আউটপুট হিসাবে পূর্ববর্তী মান পাবেন। সুতরাং আপনাকে setStateফাংশনে কলব্যাকে কনসোলটি লিখতে হবে

openAddBoardModal() {
  this.setState({ boardAddModalShow: true }, function () {
    console.log(this.state.boardAddModalShow);
  });
}

setStateঅ্যাসিঙ্ক্রোনাস হয়। এর অর্থ হল আপনি এটিকে এক লাইনে কল করতে পারবেন না এবং ধরে নেবেন যে পরের দিকে রাষ্ট্রটির পরিবর্তন হয়েছে।

প্রতিক্রিয়া ডক্স অনুসারে

setState()তাত্ক্ষণিকভাবে পরিবর্তিত হয় না this.stateতবে একটি বিচারাধীন রাষ্ট্রের রূপান্তর তৈরি করে। this.stateএই পদ্ধতিটি কল করার পরে অ্যাক্সেস করা সম্ভাব্যভাবে বিদ্যমান মানটি ফিরিয়ে আনতে পারে। সেটস্টেটে কলগুলি সিঙ্ক্রোনাস অপারেশনের কোনও গ্যারান্টি নেই এবং কলগুলি পারফরম্যান্স লাভের জন্য ব্যাচ করা যেতে পারে।

কেন তারা setStateঅ্যাসিঙ্ক তৈরি করবে

এটি কারণ setStateরাষ্ট্র পরিবর্তন করে এবং পুনঃস্থাপনের কারণ হয়। এটি একটি ব্যয়বহুল অপারেশন হতে পারে এবং এটিকে সিঙ্ক্রোনাস করা ব্রাউজারটিকে প্রতিক্রিয়াবিহীন ছেড়ে দিতে পারে।

সুতরাং setStateকলগুলি অ্যাসিক্রোনাসের পাশাপাশি আরও ভাল ইউআই অভিজ্ঞতা এবং পারফরম্যান্সের জন্য ব্যাচড।


এখন অবধি এটি দুর্দান্ত ধারণা, তবে আপনি যদি এসলিন্টের নিয়ম ব্যবহার করছেন বলে আমরা যদি কনসোল.লগ ব্যবহার করতে না পারি তবে কী হবে?
maudev

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

4
কলব্যাক যদি আপনি বলেছিলেন কাজ না করে? আমার না!
অ্যালেক্স জোলিগ

@ শুভখত্রি এটি আমার পক্ষে দুর্দান্ত কাজ করেছে, তবে আমি তখন রাষ্ট্রের মানটিকে একটি সন্তানের উপাদান হিসাবে প্রপোজ হিসাবে দেওয়ার চেষ্টা করেছি এবং যখন আমি console.logপ্রপস করি তখন আমি মূল রাষ্ট্রের মতোই মূল্য পাই।
আর্কি মার্গ্রেটস

36

ভাগ্যক্রমে setState() কলব্যাক নেয়। এবং এখানেই আমরা আপডেট রাষ্ট্র get

এই উদাহরণ বিবেচনা করুন।

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

সুতরাং কলব্যাক আগুনের সময়, এই.স্টেটটি আপডেট হওয়া রাষ্ট্র।
আপনি mutated/updatedকলব্যাকে ডেটা পেতে পারেন ।


4
আপনি যে কোনও ফাংশন পাস করার জন্য এই কলব্যাকটিও ব্যবহার করতে পারেন initMap(), উদাহরণস্বরূপ
ডেন্ডে

যাওয়ার পথে! অবশেষে আমার সমস্যার সমাধান। অনেক ধন্যবাদ.
আহমেট হালিলোভিć

12

যেহেতু সেটসেটটি একটি অ্যাসিঙ্ক্রোনাস ফাংশন তাই আপনাকে রাজ্যের এইরকম কলব্যাক হিসাবে কনসোল করতে হবে।

openAddBoardModal(){
    this.setState({ boardAddModalShow: true }, () => {
        console.log(this.state.boardAddModalShow)
    });
}

7

setState()সর্বদা অবিলম্বে উপাদানটি আপডেট করে না। এটি ব্যাচ করতে পারে বা পরে পর্যন্ত আপডেটটিকে পিছিয়ে দিতে পারে। এটি setState()সম্ভাব্য ক্ষতির কল করার পরে ঠিক এই স্টেটটি পড়া দেয় । পরিবর্তে, ব্যবহার করুন componentDidUpdateবা একটি setStateকলব্যাক ( setState(updater, callback)), যার মধ্যে কোনওটি আপডেট প্রয়োগের পরে আগুনের গ্যারান্টিযুক্ত। আপনি যদি পূর্ববর্তী রাজ্যের উপর ভিত্তি করে রাজ্যটি সেট করতে চান তবে নীচে আপডেটের যুক্তি সম্পর্কে পড়ুন।

setState()shouldComponentUpdate()মিথ্যা ফেরত না দিলে সর্বদা রি-রেন্ডারে নিয়ে যায় । যদি পরিবর্তনীয় অবজেক্ট ব্যবহার করা হয় এবং শর্তাধীন রেন্ডারিং লজিক প্রয়োগ করা যায় না shouldComponentUpdate(), setState()কেবল তখনই কল করা যখন নতুন রাজ্য পূর্ববর্তী রাজ্যের থেকে পৃথক হয় কেবল অযৌক্তিক পুনরায় রেন্ডারগুলি এড়াতে পারে।

প্রথম যুক্তিটি স্বাক্ষর সহ আপডেটের ফাংশন:

(state, props) => stateChange

stateপরিবর্তনটি প্রয়োগ করা হচ্ছে এমন সময়ে উপাদানগুলির একটি সূত্র। এটি সরাসরি পরিবর্তন করা উচিত নয়। পরিবর্তে, পরিবর্তনগুলি রাষ্ট্র এবং প্রপস থেকে ইনপুট উপর ভিত্তি করে একটি নতুন অবজেক্ট তৈরি করে প্রতিনিধিত্ব করা উচিত। উদাহরণস্বরূপ, ধরুন আমরা প্রপস স্টেপ দ্বারা রাষ্ট্রের কোনও মান বৃদ্ধি করতে চেয়েছিলাম:

this.setState((state, props) => {
    return {counter: state.counter + props.step};
});

2

আপনি যদি রাষ্ট্রটি আপডেট করতে চান বা না তা ট্র্যাক করতে চান তবে একই জিনিসটি করার অন্য একটি উপায়

_stateUpdated(){
  console.log(this.state. boardAddModalShow);
}

openAddBoardModal(){
  this.setState(
    {boardAddModalShow: true}, 
    this._stateUpdated.bind(this)
  );
}

আপনি যখনই ডিবাগিংয়ের জন্য রাষ্ট্র আপডেট করার চেষ্টা করবেন তখন আপনি এই পদ্ধতিটিকে "_stateUpdated" কল করতে পারেন।


1

setState()অ্যাসিঙ্ক্রোনাস হয়। রাজ্য আপডেট হচ্ছে কিনা তা যাচাই করার সর্বোত্তম উপায়টি হবে componentDidUpdate()এবং console.log(this.state.boardAddModalShow)পরে কিছু দেওয়া হবে না this.setState({ boardAddModalShow: true })

প্রতিক্রিয়া দস্তাবেজ অনুসারে

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


1

প্রতিক্রিয়া ডক্স অনুসারে

প্রতিক্রিয়া গ্যারান্টি দেয় না যে রাষ্ট্র পরিবর্তনগুলি অবিলম্বে প্রয়োগ করা হবে। এটি সেটস্টেট () কে একটি সম্ভাব্য বলার পরে ডাবল স্টেটটি পড়া ঠিক করে তোলে pitfallএবং প্রকৃতির existingকারণে সম্ভাব্যভাবে মানটি ফিরিয়ে দিতে asyncপারে। পরিবর্তে, ব্যবহার componentDidUpdateবা setStateসেটস্টেট অপারেশন সফল হওয়ার পরেই কার্যকর করা একটি কলব্যাক। সাধারণভাবে আমরা componentDidUpdate()পরিবর্তে এই জাতীয় যুক্তির জন্য ব্যবহারের পরামর্শ দিই ।

উদাহরণ:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      counter: 1
    };
  }
  componentDidUpdate() {
    console.log("componentDidUpdate fired");
    console.log("STATE", this.state);
  }

  updateState = () => {
    this.setState(
      (state, props) => {
        return { counter: state.counter + 1 };
      });
  };
  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <button onClick={this.updateState}>Update State</button>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);


1

হুকস সহ যে কেউ এটি করার চেষ্টা করছে তাদের জন্য আপনার প্রয়োজন useEffect

function App() {
  const [x, setX] = useState(5)
  const [y, setY] = useState(15) 

  console.log("Element is rendered:", x, y)

  // setting y does not trigger the effect
  // the second argument is an array of dependencies
  useEffect(() => console.log("re-render because x changed:", x), [x])

  function handleXClick() {
    console.log("x before setting:", x)
    setX(10)
    console.log("x in *line* after setting:", x)
  }

  return <>
    <div> x is {x}. </div>
    <button onClick={handleXClick}> set x to 10</button>
    <div> y is {y}. </div>
    <button onClick={() => setY(20)}> set y to 20</button>
  </>
}

আউটপুট:

Element is rendered: 5 15
re-render because x changed: 5
(press x button)
x before setting: 5
x in *line* after setting: 5
Element is rendered: 10 15
re-render because x changed: 10
(press y button)
Element is rendered: 10 20

-1

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

componentDidUpdate(){}

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

https://images.app.goo.gl/BVRAi4ea2P4LchqJ8


-2
 this.setState({
    isMonthFee: !this.state.isMonthFee,
  }, () => {
    console.log(this.state.isMonthFee);
  })

4
সর্বাধিক উত্সাহিত উত্তরটি ঠিক এটি ব্যাখ্যা করে তবে কোনও ব্যাখ্যা ছাড়াই এবং 3 বছর দেরি করে। সদৃশ জবাবগুলি পোস্ট করার জন্য দয়া করে এটিতে যুক্ত করার জন্য আপনার কিছু প্রাসঙ্গিক না থাকে।
এমিল বার্গারন

-2

হ্যাঁ কারণ সেটস্টেট একটি অ্যাসিনক্রোনাস ফাংশন। আপনি রাষ্ট্র স্থির লেখার ঠিক পরে রাষ্ট্র নির্ধারণের সর্বোত্তম উপায় হ'ল অবজেক্ট.সেসাইন ব্যবহার করে: উদাহরণস্বরূপ আপনি কোনও সম্পত্তি সেট করতে চান সত্যের পক্ষে বাতিল, এটি এটি করুন


অবজেক্ট.সেসাইন (এটি.সেটেট, {আইভিড: সত্য})


এই লাইনটি লেখার পরে আপনি আপডেট হওয়া অবস্থায় অ্যাক্সেস করতে পারবেন।


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