تفاعل حالة رد فعل بدون سبب

1

مشكلتي سهلة الفهم.

لدي قائمة مستخدمين في ولايتي. معبأ بمكالمة DataBase. ولدي أيضًا مستخدم محدد مملوء عند النقر على عنصر في قائمة المستخدمين.

عند النقر على هذا العنصر من قائمة المستخدمين ، يتم فتح مشروط بإدخال بقيمة افتراضية مملوءة من قبل المستخدم المحدد.

قمت بتعيين وظيفة onChange لهذه المدخلات ، ثم يتم حفظ كل تغيير في المستخدم المحدد.

ولكن المشكلة هي أن كل تغيير يتم حفظه أيضًا في قائمة المستخدمين وأنا لا أفهم لماذا.

لا تحتوي قائمة المستخدمين هذه على أي setState في الرمز باستثناء مكالمة البيانات من قاعدة البيانات.

class Users extends Component {
 constructor(props) {
  super(props);
   this.state = {
    userlist: [],
    selecteduser: [],
    IsModalUserVisible: false
   };
 }

ثم اتصل بالبيانات واحفظها في قائمة المستخدمين.

 componentWillMount() {
 db.collection("user")
 .get()
 .then(collection => {
   this.setState({
     userlist: collection.docs.map(doc => doc.data())
   });
 });
}

هنا هو onChange من الإدخال

handleChangeEmail(event) {
 event.preventDefault();
 const selectedUserUpdate = this.state.selecteduser;
 selectedUserUpdate.email = event.target.value;
 this.setState({
  selecteduser: selectedUserUpdate
 });
}

وهنا الوظيفة تسمى onClick على عنصر قائمة المستخدمين.

UserSelected(user) {
 this.setState({
    selecteduser: user,
    IsModalUserVisible: true
  });
}

خريطة المستخدم لإظهار قائمة المستخدمين.

{this.state.userlist.map(user => {
  return (
    <UserItem
      callback={() => this.UserSelected(user)}
      key={user.email}
      email={user.email}
    />
  );
})}

وللإنهاء ، يقوم المستخدم بإدارة مشروط ، يتم فتحه عند النقر على عنصر قائمة المستخدمين.

<ManageUserItem
   isOpen={this.state.IsModalUserVisible}
   email={this.state.selecteduser.email}
   changeEmail={this.handleChangeEmail.bind(this)}
/>

لذلك ، عندما أقوم بتغيير البريد الإلكتروني داخل الإدخال ، يمكنني أن أرى في الخلفية أن القائمة تتغير أيضًا. وتحققت مع وحدة تحكم. (this.state.userlist) في handleChangeEmail ، يمكنني رؤية قائمة المستخدمين محدثة أيضًا.

أردت أن أكون واضحًا ، ولكن آمل ألا تستغرق وقتًا طويلاً للقراءة.

شكرا لك مقدما :)

1 إجابة

1
افضل جواب

userlist: collection.docs.map(doc => doc.data()) ينشئ مصفوفة جافا سكريبت تحتوي في كل فهرس على نقطة مرجعية للذاكرة للبيانات التي يتم إرجاعها بواسطة doc.data() . عند تهيئة <UserItem> المكون ، أنت تزود هذا المكون بنفس مرجع الذاكرة في العنصر userlist صفيف الدولة. عند النقر على المستخدم ، يتم تمرير نفس المرجع من خلال callback طريقة سند UserSelected وبهذه الطريقة يتم تعيين نفس مرجع الذاكرة لمتغير الحالة selecteduser . في وقت لاحق عندما يتم التعامل مع تغيير البريد الإلكتروني لهذا المستخدم المحدد ، فإن الطريقة handleChangeEmail يعمل على مرجع الذاكرة المخزنة في مكانين ، userlist صفيف و selecteduser موضوع. عندما تقوم بتحديث سمة مرجع كائن ، فإن أي مكان آخر يتم الرجوع إليه الكائن سيظهر مثل هذه الطفرة لأنها تشير إلى نفس البيانات الأساسية. تغيير طفيف واحد أود أن أقترح على هذا الرمز في constructor طريقة التهيئة selecteduser أن يكون كائنًا ({}) وليس مصفوفة ([]) منذ ذلك الحين selecteduser في النهاية يتم تعيين كائن على أي حال وليس مصفوفة. أخيرًا ، إذا كنت تفضل ذلك selecteduser لا يكون نفس مرجع الكائن كما هو مشار إليه في userlist الصفيف ، يمكنك إنشاء كائن جديد (وبالتالي مرجع كائن جديد) من كل كائن المشار إليه في userlist مجموعة مصفوفة. مثل ذلك:

{this.state.userlist.map(user => {
   // this is one way to do it, you can find others elsewhere on SO for more complex cases.
   // Look into, Javascript as a pass by reference language versus pass by value languages
   // and their nuances. 
   const newObject = JSON.parse(JSON.stringify(user))
   return (
    <UserItem
      callback={() => this.UserSelected(newObject)}
      key={newObject.email}
      email={newObject.email}
    />
  );
})}
:مؤلف
فوق
قائمة طعام