تبديل الأزرار في React

أحاول إنشاء عنصر زر تبديل بزرين ، حيث يؤدي النقر على أحدهما إلى تعطيل الآخر والعكس. لدي حالة معاقدة أعلم أنه يجب علي التبديل. لكنني لست متأكدًا من كيفية تفريغ المنطق. يجب أن يكون هناك حالة واحدة تعطيل أو اثنين لأن هناك اثنين من أزرار؟

  constructor(props) {
      super(props);
      this.state = { disabled: false }
    }

clicky(e) {
  //should dictate the toggle logic
}

render() {
  <div onClick={this.clicky.bind(this)}>
    <button disabled={this.state.disabled}>Item 1</button>
    <button disabled={this.state.disabled}>Item 2</button>
  </div>
}
0
أعتقد أنه يجب أن يكون لديك حالة تعطيل اثنين ، أو يمكنك فقط لديك ولاية واحدة لحفظ أي زر متوافرة
وأضاف المؤلف qskane, مصدر

4 إجابة

يجب أن يفعل هذا:

constructor(props) {
  super(props);
  this.state = { button1Disabled: false }
}

clicky() {
  this.setState(prevState => ({
    button1Disabled: !prevState.button1Disabled
  }));
}

render() {
  return (
    <div onClick={this.clicky.bind(this)}>
      <button disabled={this.state.button1Disabled}>Item 1</button>
      <button disabled={!this.state.button1Disabled}>Item 2</button>
    </div>
  )
}
0
وأضاف
Chris yikes !!!
وأضاف المؤلف Dane, مصدر
AnilRedshift ، ليس صحيحًا. حله على ما يرام تماما. لن تحصل على ما تصفه بهذا الحل.
وأضاف المؤلف Chris, مصدر
Dane ، لقد نسيت أن تنكر القيمة السابقة على الرغم من ! في setState.
وأضاف المؤلف Chris, مصدر
AnilRedshift ، setState من منفصلة لا يمكن معالجات الأحداث أن يتم تجميعها ، لذا لن يحدث ذلك أبدًا. ولكن حتى لو قاموا بذلك ، فإن استخدام setState الوظيفي يضمن في الواقع أن يتم وضعهم في قائمة الانتظار بدلاً من تجميعها. تمرير كائن بدلاً من ذلك هو ما يمكن أن يحصل على التحديثات المجمعة (إذا كنا نتحدث عن setState داخل نفس المعالج ، ولكن هذه ليست الحالة هنا).
وأضاف المؤلف Chris, مصدر
هذا لا ينجح إذا انتهى الأمر بالنقر على الزر عدة مرات قبل أن يأتي الطلاء التالي
وأضاف المؤلف AnilRedshift, مصدر
Chris: ضع في اعتبارك أنه يمكنك الهريس button1 عدة مرات. في رد فعل ، ليس هناك ما يضمن أن تقديم يحدث على الفور ، وخاصة مع الألياف القادمة. ما يحدث هو أن ينتهي بك الأمر إلى تبديل الحالة ذهابًا وإيابًا ، ولكن ما يجب عليك فعله هو تعطيل العنصر 1 ، بغض النظر عن عدد مرات النقر عليه
وأضاف المؤلف AnilRedshift, مصدر
انقر فوق الحدث ، انقر فوق الحدث ، انقر فوق الحدث ، انقر فوق الحدث .... يتم استدعاء كافة دفعات ثم بشكل غير متزامن the clicky . يجب أن يكون السلوك المتوقع هو تعطيل الزر 1 بغض النظر عن عدد مرات النقر فوقه
وأضاف المؤلف AnilRedshift, مصدر

داين لديه أفضل إجابة (في رأيي) حتى الآن ، وإجابتي مشابهة تمامًا له. على الرغم من أنني أرغب في تقديم بعض الاقتراحات الأخرى:

  • أولها نقل مستمعي الأحداث خارج القسم وإرفاقه بكل من الأزرار. السبب الرئيسي وراء تحسين إمكانية الوصول (مثل قارئات الشاشة) لأن العناصر الثابتة مثل div ، p ، إلخ ، ليس لها معنى دلالي. إلى جانب ذلك ، من المنطقي أن يكون الزر الفعلي هو الذي يقوم بتشغيل شيء ما ، بدلاً من غلاف الأزرار.

  • اقتراحي الثاني هو نقل ارتباطك clicky() الخاص بك إلى المُنشئ بدلاً من ذلك. سيؤدي هذا إلى منع المكون من التجليد على كل إعادة عرض ، وسيتم ذلك بدلاً من ذلك فقط مرة واحدة على تركيب المكون.

هنا نسخة معدلة من حل Danes:

constructor(props) {
  super(props);
  this.state = { button1Disabled: false }
  this.clicky = this.clicky.bind(this);
}

clicky() {
  this.setState(prevState => ({
    button1Disabled: !prevState.button1Disabled
  }));
}

render() {
  return (
    <div>
      <button onClick={this.clicky} disabled={this.state.button1Disabled}>Item 1</button>
      <button onClick={this.clicky} disabled={!this.state.button1Disabled}>Item 2</button>
    </div>
  )
}
0
وأضاف

بدلاً من الاحتفاظ بالقيمة المنطقية ، يمكنك الاحتفاظ بمعرف الزر في حالة التعطيل ، والتي يمكن أن تصل إلى أي عدد من الأزرار بدلاً من اثنين فقط

constructor(props) {
    super(props);
    this.state = { disabled: "1" }
}

clicky(e) {
  //should dictate the toggle logic
  const id = e.target.id
  this.setState({ disabled: id })
}

render() {
  <div onClick={this.clicky.bind(this)}>
    <button disabled={this.state.disabled === "1"} id="1">Item 1</button>
    <button disabled={this.state.disabled === "2"} id="2">Item 2</button>
  </div>
}

العرض التوضيحي للعمل

0
وأضاف
AnilRedshift يمكنك دائمًا إعادة استخدام المكوّن ، ما عليك سوى تغيير المُعرّف كما هو الحال في تغيير بياناتك. في الواقع ، يمكن أن يصبح الزر مكونًا بحد ذاته ويحصل على المعرف كدعم من الأصل ويستخدمه
وأضاف المؤلف Shubham Khatri, مصدر
لا يُنصح باستخدام المعرفات في مكونات التفاعل حيث لا يمكنك إعادة استخدام المكون (أو لا يجب أن يكون على أي حال). أفضل طريقة هي استخدام البيانات ، أو دعم المرجع.
وأضاف المؤلف AnilRedshift, مصدر

نظرًا لأن الأزرار مرتبطة بشكل عكسي ، فإن إحدى الحالات هي فكرة أفضل ، لأنه مع متغيرين ، يمكن الخروج من المزامنة. أيضًا ، نظرًا لأنه يتم تمكين زر واحد فقط في كل مرة ، تكون الحالة الإدارية بسيطة ، تحتاج فقط إلى تبديل الحالة في كل مرة يتم فيها النقر على زر:

constructor(props) {
     super(props);
     this.item1 = React.createRef();
     this.item2 = React.createRef();
     this.state = { enableFirst: true }
   }

clicky(e) {
  const enableFirst = e.target !== item1;
  this.setState({ enableFirst });
}

render() {
 <div onClick={this.clicky.bind(this)}>
   <button ref={item1} disabled={this.state.enableFirst}>Item 1</button>
   <button ref={item2} disabled={!this.state.enableFirst}>Item 2</button>
 </div>
}
0
وأضاف
كيف سيخرجون من المزامنة؟
وأضاف المؤلف Chris, مصدر