হুক্স ব্যবহারের স্টেট () অবজেক্ট সহ প্রতিক্রিয়া জানায়


100

হুক্সের সাথে প্রতিক্রিয়া দেখিয়ে, রাষ্ট্রের আপডেট করার সঠিক উপায় কী?

export Example = () => {
  const [exampleState, setExampleState] = useState(
  {masterField: {
        fieldOne: "a",
        fieldTwo: {
           fieldTwoOne: "b"
           fieldTwoTwo: "c"
           }
        }
   })

কিভাবে এক ব্যবহার করেন setExampleStateআপডেটে exampleStateকরতে a(একটি ক্ষেত্র সংযোজন)?

const a = {
masterField: {
        fieldOne: "a",
        fieldTwo: {
           fieldTwoOne: "b",
           fieldTwoTwo: "c"
           }
        },
  masterField2: {
        fieldOne: "c",
        fieldTwo: {
           fieldTwoOne: "d",
           fieldTwoTwo: "e"
           }
        },
   }
}

b (মান পরিবর্তন করা)?

const b = {masterField: {
        fieldOne: "e",
        fieldTwo: {
           fieldTwoOne: "f"
           fieldTwoTwo: "g"
           }
        }
   })


আপনি বিদ্যমান অবজেক্টে নতুন অবজেক্ট কী মান যুক্ত করতে চান?
মাত্র

@ জাস্টকোড প্রথম উদাহরণের জন্য হ্যাঁ, দ্বিতীয় উদাহরণের জন্য কেবল বিদ্যমান অবজেক্টে পরিবর্তন করা হচ্ছে
ইসাএকসুলতান

উত্তর:


106

আপনি এর মতো নতুন মান পাস করতে পারেন

  setExampleState({...exampleState,  masterField2: {
        fieldOne: "c",
        fieldTwo: {
           fieldTwoOne: "d",
           fieldTwoTwo: "e"
           }
        },
   }})

4
দুর্দান্ত, যে উত্তর দেয় একটি অংশ! আপনি খ অংশ জন্য সেরা অনুশীলন জানেন?
ইসাকসুলতান

4
new // নতুন মানগুলি masterFieldinstead এর পরিবর্তে কেবল masterField2 setExampleState({...exampleState, masterField:
অতীতেরও

4
স্প্রেড অপারেটরটি ব্যবহার করার সময় অগভীর অনুলিপি সম্পর্কে সচেতন হন। উদাহরণস্বরূপ দেখুন: স্ট্যাকওভারফ্লো.com
মার্কোস গ্রিস

7
আপনি যদি তার ডিসপ্যাচারের সাথে একই অবস্থা ব্যবহার করেন তবে আপনার কোনও ফাংশন ব্যবহার করা উচিত। setExampleState( exampleState => ({...exampleState, masterField2: {...etc} }) );
মাইকেল হারলে

41

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

একবার আপনি রাজ্যের গভীরভাবে ক্লোন হয়ে গেলে, প্রতিক্রিয়া পরিবর্তন না হওয়া সত্ত্বেও, ভেরিয়েবলগুলির উপর নির্ভর করে সমস্ত কিছু পুনরায় গণনা করে এবং পুনরায় রেন্ডার করে দেয়!

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

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


ততক্ষণে গভীর ক্লোনিং না করে এবং অপ্রয়োজনীয় আপডেটগুলি নিয়ে চিন্তা না করে জটিল (স্থানীয় এবং বিশ্বব্যাপী) রাষ্ট্রীয় ডেটা পরিচালনা করতে আপনি হুকস্টেট (অস্বীকৃতি: আমি একজন লেখক ) ও ব্যবহার করতে পারেন - হুকস্টেট এটি আপনার জন্য পরিচালনা করবে।
অ্যান্ড্রু

40

কেউ যদি জন্য অনুসন্ধানের useState () জন্য আপডেট আঙ্গুলসমূহ বস্তুর

- Through Input

        const [state, setState] = useState({ fName: "", lName: "" });
        const handleChange = e => {
            const { name, value } = e.target;
            setState(prevState => ({
                ...prevState,
                [name]: value
            }));
        };

        <input
            value={state.fName}
            type="text"
            onChange={handleChange}
            name="fName"
        />
        <input
            value={state.lName}
            type="text"
            onChange={handleChange}
            name="lName"
        />
   ***************************

 - Through onSubmit or button click
    
        setState(prevState => ({
            ...prevState,
            fName: 'your updated value here'
         }));

4
ঠিক আমি খুঁজছেন ছিল কি. অসাধারণ!
স্ট্যাকড অ্যাক্টর

7

ধন্যবাদ ফিলিপ এটি আমাকে সহায়তা করেছিল - আমার ব্যবহারের ক্ষেত্রে আমার প্রচুর ইনপুট ক্ষেত্রের একটি ফর্ম ছিল তাই আমি প্রাথমিক অবস্থা অবজেক্ট হিসাবে বজায় রেখেছি এবং আমি অবজেক্টের স্থিতি আপডেট করতে সক্ষম হইনি above উপরের পোস্টটি আমাকে সহায়তা করেছে :)

const [projectGroupDetails, setProjectGroupDetails] = useState({
    "projectGroupId": "",
    "projectGroup": "DDD",
    "project-id": "",
    "appd-ui": "",
    "appd-node": ""    
});

const inputGroupChangeHandler = (event) => {
    setProjectGroupDetails((prevState) => ({
       ...prevState,
       [event.target.id]: event.target.value
    }));
}

<Input 
    id="projectGroupId" 
    labelText="Project Group Id" 
    value={projectGroupDetails.projectGroupId} 
    onChange={inputGroupChangeHandler} 
/>



6

আমি পার্টিতে দেরি করছি .. :)

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

অবস্থা:

const [infoData, setInfoData] = useState({
    major: {
      name: "John Doe",
      age: "24",
      sex: "M",
    },

    minor:{
      id: 4,
      collegeRegion: "south",

    }

  });

একটি নির্দিষ্ট রেকর্ড আপডেট করার জন্য পূর্ববর্তী রাজ্যে একটি পুনর্বিবেচনা করা প্রয়োজন prevState

এখানে:

setInfoData((prevState) => ({
      ...prevState,
      major: {
        ...prevState.major,
        name: "Tan Long",
      }
    }));

সম্ভবত

setInfoData((prevState) => ({
      ...prevState,
      major: {
        ...prevState.major,
        name: "Tan Long",
      },
      minor: {
        ...prevState.minor,
        collegeRegion: "northEast"

    }));

আমি আশা করি এটি একই ধরণের সমস্যা সমাধানের চেষ্টা করা সকলকে সহায়তা করে।


আমার একটা প্রশ্ন আছে. কেন আমাদের বন্ধনীতে ফাংশনটি মোড়ানো দরকার? হুডের নীচে কী চলছে তা আমি নিশ্চিত নই। আপনি জানতে হবে বা আমি যেখানে আরও পড়তে পারি?
জেনন

4
@ মিশেলরামেজ কেন আমরা প্রথম কার্যটি বন্ধনীতে গুটিয়ে রাখি:: এর ()সহজ উত্তর দিতে; এটি কারণ setInfoData প্রকৃতির দ্বারা উচ্চতর অর্ডারের অর্থাত্ হুক: ইউজস্টেটের দ্বারা প্রদত্ত পাওয়ার সৌজন্যে এটি একটি যুক্তি হিসাবে অন্য কাজ করতে পারে। আমি আশা করি এই নিবন্ধটি উচ্চ-অর্ডার ফাংশন উপর আরো স্বচ্ছতা প্রদান করবে: sitepoint.com/higher-order-functions-javascript
Olamigoke ফিলিপ

4
অত্যন্ত সহায়ক, বিশেষ করে যদি যেখানে আপনি একটি সম্পত্তি নেস্টেড বেশ কয়েক স্তর গভীর, অর্থাত আপডেট করার চেষ্টা করছেন জন্য: first.second.third - অন্য উদাহরণ first.second আবরণ কিন্তু first.second.third না
ক্রেগ Presti - MSFT

3
function App() {

  const [todos, setTodos] = useState([
    { id: 1, title: "Selectus aut autem", completed: false },
    { id: 2, title: "Luis ut nam facilis et officia qui", completed: false },
    { id: 3, title: "Fugiat veniam minus", completed: false },
    { id: 4, title: "Aet porro tempora", completed: true },
    { id: 5, title: "Laboriosam mollitia et enim quasi", completed: false }
  ]);

  const changeInput = (e) => {todos.map(items => items.id === parseInt(e.target.value) && (items.completed = e.target.checked));
 setTodos([...todos], todos);}
  return (
    <div className="container">
      {todos.map(items => {
        return (
          <div key={items.id}>
            <label>
<input type="checkbox" 
onChange={changeInput} 
value={items.id} 
checked={items.completed} />&nbsp; {items.title}</label>
          </div>
        )
      })}
    </div>
  );
}

1

আমি মনে করি সবচেয়ে ভালো সমাধান হয় ইম্মেরের । এটি আপনাকে অবজেক্ট আপডেট করার অনুমতি দেয় যেমন আপনি সরাসরি ক্ষেত্রগুলি পরিবর্তন করছেন (মাস্টারফিল্ড.ফিল্ডফিলন.ফিল্যান্ড = 'এবিসি')। তবে এটি অবশ্যই আসল অবজেক্টকে পরিবর্তন করবে না। এটি একটি খসড়া অবজেক্টের সমস্ত আপডেট সংগ্রহ করে এবং শেষে আপনাকে একটি চূড়ান্ত অবজেক্ট দেয় যা আপনি আসল অবজেক্টটি প্রতিস্থাপন করতে ব্যবহার করতে পারেন।


0

অবিচ্ছিন্নভাবে অবজেক্টগুলিকে আপডেট করার জন্য আমি আপনাকে একটি ইউটিলিটি ফাংশন রেখেছি

/**
 * Inmutable update object
 * @param  {Object} oldObject     Object to update
 * @param  {Object} updatedValues Object with new values
 * @return {Object}               New Object with updated values
 */
export const updateObject = (oldObject, updatedValues) => {
  return {
    ...oldObject,
    ...updatedValues
  };
};

সুতরাং আপনি এটি এটি ব্যবহার করতে পারেন

const MyComponent = props => {

  const [orderForm, setOrderForm] = useState({
    specialities: {
      elementType: "select",
      elementConfig: {
        options: [],
        label: "Specialities"
      },
      touched: false
    }
  });


// I want to update the options list, to fill a select element

  // ---------- Update with fetched elements ---------- //

  const updateSpecialitiesData = data => {
    // Inmutably update elementConfig object. i.e label field is not modified
    const updatedOptions = updateObject(
      orderForm[formElementKey]["elementConfig"],
      {
        options: data
      }
    );
    // Inmutably update the relevant element.
    const updatedFormElement = updateObject(orderForm[formElementKey], {
      touched: true,
      elementConfig: updatedOptions
    });
    // Inmutably update the relevant element in the state.
    const orderFormUpdated = updateObject(orderForm, {
      [formElementKey]: updatedFormElement
    });
    setOrderForm(orderFormUpdated);
  };

  useEffect(() => {
      // some code to fetch data
      updateSpecialitiesData.current("specialities",fetchedData);
  }, [updateSpecialitiesData]);

// More component code
}

যদি না হয় তবে আপনার এখানে আরও বেশি সুবিধা রয়েছে: https://es.reactjs.org/docs/update.html


0

শুরুতে আমি ইউজস্টেটে অবজেক্ট ব্যবহার করতাম, তবে তারপরে আমি জটিল মামলার জন্য ব্যবহারকারীর হুডে চলে যাই। আমি কোডটি রিফ্যাক্ট করেছিলাম তখন আমি পারফরম্যান্সের উন্নতি অনুভব করেছি।

যখন আপনার একাধিক সাব-মান যুক্ত থাকে বা যখন পরবর্তী রাজ্যটি পূর্বেরটির উপর নির্ভর করে তখন জটিল স্টেট লজিক থাকে এমন সময়ে স্টেটটি ব্যবহারের জন্য সাধারণত স্ট্রেসর ব্যবহার করা ভাল।

ব্যবহারকারক প্রতিক্রিয়া ডক্স

আমি ইতিমধ্যে আমার নিজস্ব ব্যবহারের জন্য এই জাতীয় হুক প্রয়োগ করেছি:

/**
 * Same as useObjectState but uses useReducer instead of useState
 *  (better performance for complex cases)
 * @param {*} PropsWithDefaultValues object with all needed props 
 * and their initial value
 * @returns [state, setProp] state - the state object, setProp - dispatch 
 * changes one (given prop name & prop value) or multiple props (given an 
 * object { prop: value, ...}) in object state
 */
export function useObjectReducer(PropsWithDefaultValues) {
  const [state, dispatch] = useReducer(reducer, PropsWithDefaultValues);

  //newFieldsVal={[field_name]: [field_value], ...}
  function reducer(state, newFieldsVal) {
    return { ...state, ...newFieldsVal };
  }

  return [
    state,
    (newFieldsVal, newVal) => {
      if (typeof newVal !== "undefined") {
        const tmp = {};
        tmp[newFieldsVal] = newVal;
        dispatch(tmp);
      } else {
        dispatch(newFieldsVal);
      }
    },
  ];
}

আরো সম্পর্কিত আঙ্গুলসমূহ

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