Bereaksi Js menerapkan atribut kelas secara kondisional

334

Saya ingin memperlihatkan dan menyembunyikan grup tombol ini secara kondisional tergantung pada apa yang diteruskan dari komponen induk yang terlihat seperti ini:

<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>
    );
  }
});

Namun tidak ada yang terjadi, dengan {this.props.showBulkActions? 'show': 'hidden'}. Apakah saya melakukan sesuatu yang salah di sini?

apexdodge
sumber
Anda mungkin juga ingin mempertimbangkan react-bootstrap , karena ini mengabstraksi beberapa hal kelas menjadi properti komponen, membuat apa yang Anda coba lakukan menjadi sedikit lebih mudah.
Dancrumb

Jawaban:

591

Kurung kurawal berada di dalam string, sehingga dievaluasi sebagai string. Mereka harus berada di luar, jadi ini harus bekerja:

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

Perhatikan spasi setelah "tarik-kanan". Anda tidak ingin secara tidak sengaja memberikan kelas "pull-rightshow" alih-alih "pull-right show". Juga tanda kurung harus ada di sana.

spitfire109
sumber
3
Terima kasih! Saya harus memodifikasinya sedikit karena untuk beberapa alasan itu tidak menghasilkan btn-group pull-right sama sekali. Hanya perlihatkan atau sembunyikan.
Apexdodge
Ini sangat membantu dalam kasus-kasus tertentu di mana classnamesmungkin tidak sesuai. Jika Anda berada dalam renderfungsi Anda dan Anda memiliki map, Anda mungkin hanya tahu apakah Anda ingin menambahkan kelas pada saat Anda merendernya, jadi jawaban ini cukup berguna untuk itu.
Dave Cooper
alternatif yang bagus alih-alih memiliki banyak template bersyarat dalam membuat atau mengembalikan
devonj
@apexdodge modifikasi apa yang harus Anda lakukan. Saya memiliki masalah yang sama.
RamY
1
@RamY Salah satu caranya adalah dengan meletakkan semua kelas di dalam kondisi this.props.showBulkActions ? 'btn-group pull-right show' : 'btn-group pull-right hidden'). Tidak elegan tapi berhasil.
Ian
87

Seperti orang lain berkomentar, utilitas classnames adalah pendekatan yang saat ini direkomendasikan untuk menangani nama kelas CSS bersyarat di ReactJs.

Dalam kasus Anda, solusinya akan terlihat seperti:

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

...

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

Sebagai catatan tambahan, saya menyarankan Anda untuk mencoba menghindari penggunaan keduanya showdan hiddenkelas, sehingga kodenya bisa lebih sederhana. Kemungkinan besar Anda tidak perlu mengatur kelas untuk sesuatu yang akan ditampilkan secara default.

Diego V
sumber
11
Bisakah Anda menguraikan utilitas classNames menjadi "pendekatan yang saat ini direkomendasikan"? Apakah itu tertangkap dalam beberapa dokumen praktik terbaik yang dianggap baik di suatu tempat? Atau hanya semacam kata dari mulut di sekitar Bereaksi dan classNamessaat ini?
Alexander Nied
6
@anied Pada saat penulisan ini direkomendasikan dalam dokumentasi Bereaksi resmi: web.archive.org/web/20160602124910/http://facebook.github.io:80/…
Diego V
3
Itu masih disebutkan dalam dokumentasi terbaru : " Jika Anda sering menemukan diri Anda menulis kode seperti ini, paket classnames dapat menyederhanakannya. "
Franklin Yu
66

Jika Anda menggunakan transpiler (seperti Babel atau Traceur), Anda dapat menggunakan " string template " ES6 yang baru .

Inilah jawaban dari @ spitfire109, yang dimodifikasi sesuai:

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

Pendekatan ini memungkinkan Anda untuk melakukan hal-hal yang rapi seperti itu, memberikan salah satu s-is-shownatau s-is-hidden:

<div className={`s-${this.props.showBulkActions ? 'is-shown' : 'is-hidden'}`}>
Bertrand
sumber
20
Hati-hati dengan pendekatan kedua, terutama dalam basis kode besar, karena membuat string kelas kurang dapat diterima. Misalnya, jika seseorang mencari s-is-shownatau s-is-hiddendalam basis kode, mereka tidak akan menemukan kode ini.
tandai
15

Anda dapat menggunakan String literal di sini

const Angle = ({show}) => {

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

   return <i className={angle} />
}
Musa
sumber
9

Mengeluarkan jawaban baik @ spitfire109, orang dapat melakukan sesuatu seperti ini:

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

  return names.join(' ');
}

dan kemudian dalam fungsi render:

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

membuat jsx singkat

terkelupas
sumber
8

Atau gunakan npm classnames . Ini sangat mudah dan berguna terutama untuk membangun daftar kelas

Periksa pensil
sumber
8

Jika Anda hanya perlu satu nama kelas opsional:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? "show" : "")}>
Eugene Chybisov
sumber
1
Ini akan menambahkan falsekelas ketika kondisi gagal.
RA.
6

Anda dapat menggunakan array ES6 alih-alih nama kelas. Jawabannya didasarkan pada artikel Dr. Axel Rauschmayer: Secara kondisional menambahkan entri di dalam Array dan objek literal .

<div className={[
                 "classAlwaysPresent", 
                 ...Array.from(condition && ["classIfTrue"])
                ].join(" ")} />
Tudor Morar
sumber
tolong kembangkan ini, apa kondisinya?
mibbit
kondisi const = (1 === 1);
Tudor Morar
5

2019:

Bereaksi adalah danau banyak utilitas. Tetapi Anda tidak membutuhkan npmpaket apa pun untuk itu. buat saja suatu fungsi classnamesdan panggil ketika Anda membutuhkannya;

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

atau

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

contoh

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

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

Hanya Untuk Inspirasi

mendeklarasikan elemen pembantu dan menggunakannya togglemetode

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

contoh:

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

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

Solusi yang lebih elegan, yang lebih baik untuk pemeliharaan dan keterbacaan:

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

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

<Element className={classNames.join(' ')}/>
Nate Ben
sumber
3

Anda bisa menggunakan ini:

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

Ini akan bekerja untuk Anda

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

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

return (
            ...
            <div className={_myClasses}>
               ...
            </div>
    );
  }
});
Manoj Amalraj
sumber
1

Anda dapat menggunakan paket npm ini . Ini menangani semuanya dan memiliki opsi untuk kelas statis dan dinamis berdasarkan variabel atau fungsi.

// 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"
Tushar Sharma
sumber
1

Berdasarkan nilai this.props.showBulkActionsAnda dapat beralih kelas secara dinamis sebagai berikut.

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

Saya ingin menambahkan bahwa Anda juga dapat menggunakan konten variabel sebagai bagian dari kelas

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

Konteksnya adalah obrolan antara bot dan pengguna, dan gaya berubah tergantung dari pengirim, ini adalah hasil browser:

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

Ini berguna ketika Anda memiliki lebih dari satu kelas untuk ditambahkan. Anda bisa bergabung dengan semua kelas dalam array dengan spasi.

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

Menggantikan:

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

dengan:

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

Referensi ke @split fire answer, kita dapat memperbaruinya dengan templat literals, yang lebih mudah dibaca, Untuk referensi Checkout javascript templat literal

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

Saya menemukan ini yang menjelaskan bagaimana melakukannya dengan ternary dan dengan Classnames Library

chachan
sumber