ทำปฏิกิริยา Js โดยใช้คุณสมบัติคลาสอย่างมีเงื่อนไข


334

ฉันต้องการแสดงและซ่อนกลุ่มปุ่มตามเงื่อนไขโดยขึ้นอยู่กับสิ่งที่ส่งผ่านจากองค์ประกอบหลักซึ่งมีลักษณะดังนี้:

<TopicNav showBulkActions={this.__hasMultipleSelected} />

....

__hasMultipleSelected: function() {
  return false; //return true or false depending on data
}

....

var TopicNav = React.createClass({
render: function() {
return (
    <div className="row">
        <div className="col-lg-6">
            <div className="btn-group pull-right {this.props.showBulkActions ? 'show' : 'hidden'}">
                <button type="button" className="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
                  Bulk Actions <span className="caret"></span>
                </button>
                <ul className="dropdown-menu" role="menu">
                  <li><a href="#">Merge into New Session</a></li>
                  <li><a href="#">Add to Existing Session</a></li>
                  <li className="divider"></li>
                  <li><a href="#">Delete</a></li>
                </ul>
            </div>
        </div>
    </div>
    );
  }
});

อย่างไรก็ตามไม่มีอะไรเกิดขึ้นกับ {this.props.showBulkActions? 'show': 'hidden'} ฉันกำลังทำอะไรผิดที่นี่?


คุณอาจต้องการพิจารณาการตอบสนองการบูตเนื่องจากบทคัดย่อนี้บางสิ่งในชั้นเรียนเป็นคุณสมบัติขององค์ประกอบทำให้สิ่งที่คุณพยายามทำง่ายขึ้นเล็กน้อย
Dancrumb

คำตอบ:


590

วงเล็บปีกกาอยู่ภายในสตริงดังนั้นมันจึงถูกประเมินเป็นสตริง พวกเขาต้องอยู่ข้างนอกดังนั้นสิ่งนี้ควรจะได้ผล:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? 'show' : 'hidden')}>

สังเกตช่องว่างหลังจาก "ดึงขวา" คุณไม่ต้องการให้คลาส "pull-rightshow" โดยไม่ตั้งใจแทน "pull-right show" นอกจากนี้ยังต้องมีวงเล็บด้วย


3
ขอบคุณ! ฉันต้องแก้ไขมันเล็กน้อยเพราะเหตุผลบางอย่างมันก็ไม่ได้ส่งออก btn- กลุ่มดึงขวาเลย เพียงแสดงหรือซ่อน
apexdodge

สิ่งนี้มีประโยชน์อย่างยิ่งในบางกรณีที่classnamesอาจไม่เหมาะสม หากคุณอยู่ในrenderฟังก์ชั่นและคุณมีmapคุณอาจจะรู้ว่าคุณต้องการเพิ่มคลาสในเวลาที่คุณแสดงผลหรือไม่ดังนั้นคำตอบนี้มีประโยชน์มาก
Dave Cooper

ทางเลือกที่ดีแทนที่จะมีเทมเพลตเงื่อนไขของคุณในการแสดงผลหรือกลับ
devonj

@apexdodge คุณต้องแก้ไขอะไรบ้าง ฉันมีปัญหาเดียวกัน
RamY

1
วิธีการหนึ่งที่ @RamY this.props.showBulkActions ? 'btn-group pull-right show' : 'btn-group pull-right hidden')คือการใส่ทุกชั้นภายในเงื่อนไข ไม่หรูหรา แต่ใช้งานได้
เอียน

87

ดังที่คนอื่น ๆ ให้ความเห็นยูทิลิตี้ชื่อคลาสเป็นแนวทางที่แนะนำในปัจจุบันในการจัดการชื่อคลาส CSS แบบมีเงื่อนไขใน ReactJs

ในกรณีของคุณโซลูชันจะมีลักษณะดังนี้:

var btnGroupClasses = classNames(
  'btn-group',
  'pull-right',
  {
    'show': this.props.showBulkActions,
    'hidden': !this.props.showBulkActions
  }
);

...

<div className={btnGroupClasses}>...</div>

ในฐานะที่เป็นบันทึกด้านข้างฉันขอแนะนำให้คุณพยายามหลีกเลี่ยงการใช้ทั้งสองshowและhiddenคลาสเพื่อให้รหัสนั้นง่ายขึ้น เป็นไปได้ว่าคุณไม่จำเป็นต้องตั้งค่าคลาสเพื่อให้สิ่งที่จะแสดงเป็นค่าเริ่มต้น


11
คุณสามารถอธิบายรายละเอียดเกี่ยวกับยูทิลิตี้ classNames ว่าเป็น "แนวทางที่แนะนำในปัจจุบัน" ได้หรือไม่? นั่นถูกบันทึกไว้ในเอกสารแนวปฏิบัติที่ดีที่สุดที่ได้รับการยกย่องบางแห่งหรือไม่? หรือเพียงแค่เรียงคำพูดจากปากไปรอบ ๆ React และclassNamesในตอนนี้?
Alexander Nied

6
@anied ในขณะที่เขียนขอแนะนำในเอกสารตอบโต้
Diego V

3
มันยังคงถูกกล่าวถึงในเอกสารล่าสุด : " หากคุณมักจะพบว่าตัวเองกำลังเขียนโค้ดเช่นนี้แพ็คเกจชื่อคลาสสามารถทำให้มันง่ายขึ้น "
Franklin Yu

66

หากคุณกำลังใช้ transpiler (เช่นBabelหรือ Traceur) คุณสามารถใช้ ES6 "เท็มเพลตสตริง " ใหม่ได้

นี่คือคำตอบของ @ spitfire109, แก้ไขตาม:

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'shown' : 'hidden'}`}>

วิธีนี้ช่วยให้คุณทำสิ่งที่เรียบร้อยเช่นนั้นแสดงผลs-is-shownหรือs-is-hidden:

<div className={`s-${this.props.showBulkActions ? 'is-shown' : 'is-hidden'}`}>

20
ระวังด้วยวิธีที่สองโดยเฉพาะอย่างยิ่งในโค้ดเบสขนาดใหญ่เนื่องจากมันจะทำให้สายคลาสมีความสามารถในการจับคู่ที่น้อยลง ตัวอย่างเช่นหากมีคนค้นหาs-is-shownหรือs-is-hiddenใน codebase พวกเขาจะไม่พบรหัสนี้
ทำเครื่องหมาย

15

คุณสามารถใช้ที่นี่ตัวอักษรสตริง

const Angle = ({show}) => {

   const angle = `fa ${show ? 'fa-angle-down' : 'fa-angle-right'}`;

   return <i className={angle} />
}

9

เมื่อใช้คำตอบที่ดีของ @ spitfire109 ใคร ๆ ก็สามารถทำสิ่งนี้:

rootClassNames() {
  let names = ['my-default-class'];
  if (this.props.disabled) names.push('text-muted', 'other-class');

  return names.join(' ');
}

และจากนั้นภายในฟังก์ชั่นการแสดงผล:

<div className={this.rootClassNames()}></div>

ทำให้ jsx สั้น


8

หรือใช้ NPM classnames มันง่ายและมีประโยชน์โดยเฉพาะอย่างยิ่งสำหรับการสร้างรายการของชั้นเรียน


8

ในกรณีที่คุณต้องการชื่อคลาสทางเลือกเดียวเท่านั้น:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? "show" : "")}>

1
นี่จะผนวกfalseคลาสเมื่อเงื่อนไขล้มเหลว
RA

6

คุณสามารถใช้อาร์เรย์ ES6 แทนชื่อคลาสได้ คำตอบนั้นขึ้นอยู่กับบทความของ Dr. Axel Rauschmayer: เพิ่มรายการภายใน Array และตัวอักษรวัตถุโดยมีเงื่อนไข

<div className={[
                 "classAlwaysPresent", 
                 ...Array.from(condition && ["classIfTrue"])
                ].join(" ")} />

โปรดขยายต่อไปนี้เป็นเงื่อนไขอะไร
mibbit

เงื่อนไข const = (1 === 1);
Tudor Morar

5

2019:

ปฏิกิริยาเป็นทะเลสาบสาธารณูปโภคมากมาย แต่คุณไม่จำเป็นต้องมีnpmแพ็คเกจใด ๆ เพียงแค่สร้างฟังก์ชันclassnamesและเรียกใช้เมื่อคุณต้องการ

function classnames(obj){
  return Object.entries(obj).filter( e => e[1] ).map( e=>e[0] ).join(' ');
}

หรือ

function classnames(obj){
 return Object.entries(obj).map( ([k,v]) => v?k:'' ).join(' ');
}

ตัวอย่าง

  stateClass= {
    foo:true,
    bar:false,
    pony:2
  }
  classnames(stateClass) // return 'foo pony'

 <div className="foo bar {classnames(stateClass)}"> some content </div>

เพียงเพื่อแรงบันดาลใจ

ประกาศองค์ประกอบผู้ช่วยและใช้มันเป็นtoggleวิธีการ

(DOMToken​List)classList.toggle(class,condition)

ตัวอย่าง:

const classes = document.createElement('span').classList; 

function classstate(obj){
  for( let n in obj) classes.toggle(n,obj[n]);
 return classes; 
}

4

โซลูชันที่หรูหรากว่าซึ่งดีกว่าสำหรับการบำรุงรักษาและการอ่าน:

const classNames = ['js-btn-connect'];

if (isSelected) { classNames.push('is-selected'); }

<Element className={classNames.join(' ')}/>

3

คุณสามารถใช้สิ่งนี้:

<div className={"btn-group pull-right" + (this.props.showBulkActions ? ' show' : ' hidden')}>

2

สิ่งนี้จะได้ผลสำหรับคุณ

var TopicNav = React.createClass({
render: function() {

let _myClasses = `btn-group pull-right {this.props.showBulkActions?'show':'hidden'}`;

return (
            ...
            <div className={_myClasses}>
               ...
            </div>
    );
  }
});

1

คุณสามารถใช้นี้แพคเกจ NPM มันจัดการทุกอย่างและมีตัวเลือกสำหรับการเรียนแบบคงที่และแบบไดนามิกขึ้นอยู่กับตัวแปรหรือฟังก์ชั่น

// Support for string arguments
getClassNames('class1', 'class2');

// support for Object
getClassNames({class1: true, class2 : false});

// support for all type of data
getClassNames('class1', 'class2', null, undefined, 3, ['class3', 'class4'], { 
    class5 : function() { return false; },
    class6 : function() { return true; }
});

<div className={getClassNames('show', {class1: true, class2 : false})} /> // "show class1"

1

ตามค่าของthis.props.showBulkActionsคุณสามารถสลับคลาสแบบไดนามิกดังต่อไปนี้

<div ...{...this.props.showBulkActions 
? { className: 'btn-group pull-right show' } 
: { className: 'btn-group pull-right hidden' }}>

1

ฉันต้องการเพิ่มว่าคุณยังสามารถใช้เนื้อหาตัวแปรเป็นส่วนหนึ่งของชั้นเรียน

<img src={src} alt="Avatar" className={"img-" + messages[key].sender} />

บริบทคือการแชทระหว่างบอทและผู้ใช้และสไตล์ที่เปลี่ยนแปลงขึ้นอยู่กับผู้ส่งนี่คือผลลัพธ์ของเบราว์เซอร์:

<img src="http://imageurl" alt="Avatar" class="img-bot">

1

สิ่งนี้มีประโยชน์เมื่อคุณมีคลาสมากกว่าหนึ่งชั้นต่อท้าย คุณสามารถเข้าร่วมชั้นเรียนทั้งหมดในอาร์เรย์ด้วยช่องว่าง

const visibility = this.props.showBulkActions ? "show" : ""
<div className={["btn-group pull-right", visibility].join(' ')}>

1

แทนที่:

<div className="btn-group pull-right {this.props.showBulkActions ? 'show' : 'hidden'}">`

ด้วย:

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.