Cara menambahkan beberapa kelas ke Komponen ReactJS


346

Saya baru mengenal ReactJS dan JSX dan saya mengalami sedikit masalah dengan kode di bawah ini.

Saya mencoba menambahkan beberapa kelas ke classNameatribut pada masing-masing li:

<li key={index} className={activeClass, data.class, "main-class"}></li>

Komponen React saya adalah:

var AccountMainMenu = React.createClass({
  getInitialState: function() {
    return { focused: 0 };
  },

  clicked: function(index) {
    this.setState({ focused: index });
  },

  render: function() {
    var self = this;
    var accountMenuData = [
      {
        name: "My Account",
        icon: "icon-account"
      },
      {
        name: "Messages",
        icon: "icon-message"
      },
      {
        name: "Settings",
        icon: "icon-settings"
      }
    /*{
        name:"Help &amp; Support &nbsp; <span class='font-awesome icon-support'></span>(888) 664.6261",
        listClass:"no-mobile last help-support last"
      }*/
    ];

    return (
      <div className="acc-header-wrapper clearfix">
        <ul className="acc-btns-container">
          {accountMenuData.map(function(data, index) {
            var activeClass = "";

            if (self.state.focused == index) {
              activeClass = "active";
            }

            return (
              <li
                key={index}
                className={activeClass}
                onClick={self.clicked.bind(self, index)}
              >
                <a href="#" className={data.icon}>
                  {data.name}
                </a>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
});

ReactDOM.render(<AccountMainMenu />, document.getElementById("app-container"));

Saya menemukan jawaban singkat di sini stackoverflow.com/a/36209517/4125588 , cukup gunakan JavaScript untuk bergabung dengan kelas ini, statis atau dinamis, dengan operator '+', ingatlah untuk memasukkan '' sebelum kelas kecuali yang pertama, sebagai yang asli kelas dalam HTML harus seperti 'ab c', juga ruang di antara mereka.
Fadeoc Khaos


1
Kenapa tidak classNames={{foo: true, bar: true, baz: false}}dan classNames={["foo", "bar"]}hanya bekerja ?
Peter V. Mørch

Jawaban:


221

Saya menggunakan classnames ketika ada cukup banyak logika diperlukan untuk menentukan kelas untuk (tidak) digunakan. Contoh yang terlalu sederhana :

...
    var liClasses = classNames({
      'main-class': true,
      'activeClass': self.state.focused === index
    });

    return (<li className={liClasses}>{data.name}</li>);
...

Yang mengatakan, jika Anda tidak ingin menyertakan ketergantungan maka ada jawaban yang lebih baik di bawah ini.


188
Sayang sekali Anda harus membawa perpustakaan classnames hanya untuk menambahkan dua kelas ke elemen :(
user959690

4
@ user959690 Ini adalah contohnya. Perpustakaan ini sangat bagus ketika Anda sering melakukan hal-hal ini dan Anda memiliki logika yang kompleks tentang kapan kelas perlu diterapkan atau tidak. Jika Anda melakukan sesuatu yang sederhana maka tentu saja gunakan template, tetapi setiap kasus berbeda dan pembaca harus memilih alat yang tepat untuk pekerjaan mereka.
Jack

7
@ user959690 Perlu dicatat bahwa sekarang diinstal oleh NPM saat menggunakan Webpack , jadi import classNames from 'classnames'untuk digunakan dalam komponen className={classNames(classes.myFirstClass, classes.mySecondClass)} .
Hooligancat

5
Tidak perlu menggunakan perpustakaan eksternal, lihat jawaban saya di bawah ini.
Huw Davies

1
Perpustakaan memiliki kelebihan lain: var btnClass = classNames({ btn: true, 'btn-pressed': this.state.isPressed, 'btn-over': !this.state.isPressed && this.state.isHovered }); return <button className={btnClass}>{this.props.label}</button>;
AmitJS94

395

Saya menggunakan ES6 literal templat . Sebagai contoh:

const error = this.state.valid ? '' : 'error'
const classes = `form-control round-lg ${error}`

Dan kemudian render saja:

<input className={classes} />

Versi satu-baris:

<input className={`form-control round-lg ${this.state.valid ? '' : 'error'}`} />

157
Juga:<input className={`class1 ${class2}`}>
Cody Moniz

3
@ unyo Silakan posting komentar Anda sebagai jawaban sehingga saya bisa meningkatkannya. Itu sangat layak untuk itu. Saya sudah mencari 1 jam untuk sesuatu semudah ini, dan sekarang saya menemukan ini terkubur sebagai komentar. Terima kasih.
Souvik Ghosh

Ini menghasilkan <input class=" form-control input-lg round-lg" />. Perhatikan ruang ekstra di awal. Ini valid, tapi jelek. Bahkan bereaksi, FAQ merekomendasikan cara lain atau menggunakan paket classnames: reactjs.org/docs/faq-styling.html
Nakedible

Saya tidak dapat memahami mengapa Anda mengimpor perpustakaan (seperti dalam jawaban yang diterima) untuk hanya mengatur beberapa kelas yang dapat diatur menggunakan Vanilla JavaScript, yang merupakan solusi yang lebih efisien, lebih bersih, dan mudah dibaca.
Marcus Parsons

2
Ini jawaban yang benar. Menggunakan ketergantungan untuk ini seperti yang disarankan dalam jawaban "benar" adalah berlebihan.
TheDarkIn1978

171

Cukup gunakan JavaScript.

<li className={[activeClass, data.klass, "main-class"].join(' ')} />

Jika Anda ingin menambahkan kunci dan nilai berbasis kelas di objek Anda bisa menggunakan yang berikut:

function classNames(classes) {
  return Object.entries(classes)
    .filter(([key, value]) => value)
    .map(([key, value]) => key)
    .join(' ');
}

const classes = {
  'maybeClass': true,
  'otherClass': true,
  'probablyNotClass': false,
};

const myClassNames = classNames(classes);
// Output: "maybeClass otherClass"

<li className={myClassNames} />

Atau bahkan lebih sederhana:

const isEnabled = true;
const isChecked = false;

<li className={[isEnabled && 'enabled', isChecked && 'checked']
  .filter(e => !!e)
  .join(' ')
} />
// Output:
// <li className={'enabled'} />

Inilah garis yang bekerja untuk saya:className={['terra-Table', medOrder.resource.status]}
Doug Wilhelm

1
@ DougWilhelm Saya tidak berpikir itu berhasil. Secara implisit memanggil toString dan membuat daftar kelas yang dipisahkan koma. github.com/facebook/react/issues/3138
0xcaff

6
Ide bagus untuk menggunakannya className={[listOfClasses].join(' ')}berfungsi untuk saya, terima kasih!
Ala Eddine JEBALI

98

Concat

Tidak perlu mewah saya menggunakan modul CSS dan mudah

import style from '/css/style.css';

<div className={style.style1+ ' ' + style.style2} />

Ini akan menghasilkan:

<div class="src-client-css-pages-style1-selectionItem src-client-css-pages-style2">

Dengan kata lain, keduanya gaya

Persyaratan

Akan mudah menggunakan ide yang sama dengan if

const class1 = doIHaveSomething ? style.style1 : 'backupClass';

<div className={class1 + ' ' + style.style2} />

1
Ini bekerja untuk saya, bersama dengan nama '-', yaitu: <nav className = {styles.navbar + "" + styles ['navbar-default']}>
Flinkman

LOL, aku mematahkan kepalaku dan jawabannya sederhana: D. Tapi ini juga berfungsi dengan CSS Loader Module
GusDeCooL

Masalahnya adalah Anda tidak dapat memiliki kelas opsional (jika tidak terdefinisi, maka tidak akan ditambahkan), jadi itu tergantung Anda yakin kelas Anda bukan nol (bukan opsional). Dalam hal opsional tidak ada yang lebih baik daripada kelas pembantu seperti (). kita dapat menggunakan ternary dengan templat seperti itu className={slider $ {className? `$ {className} : ''}}` `. Tapi ini banyak. [note: 'something' + undefined = 'something underfined'. Konversi dinamis.
Mohamed Allal

Tentu Anda bisa, cukup deklarasikan variabel di atas dan gunakan secara kondisional :)
Jamie Hutber

42

Ini dapat dicapai dengan literal templat ES6:

<input className={`class1 ${class2}`}>

1
ini hampir berhasil untuk saya, saya hanya perlu menginterpolasi class1 juga dan tidak ada lagi kesalahan, jadi sepertinya ini <input className={`${class1} ${class2}`}>
Kingston Fortune

35

Anda dapat membuat elemen dengan beberapa nama kelas seperti ini:

<li className="class1 class2 class3">foo</li>

Secara alami, Anda bisa menggunakan string yang berisi nama kelas dan memanipulasi string ini untuk memperbarui nama kelas elemen.

var myClassNammes = 'class1 class2 class3';
...
<li className={myClassNames}>foo</li>

1
Apakah Anda menguji ini? Saya lakukan :)
gagak

Ya saya lakukan. Sebenarnya, saya cukup sering menggunakannya tetapi hanya melihat dan memperbaiki kesalahan ketik. Tentu saja string yang berisi nama-nama kelas di baris pertama harus dibuat menggunakan "bukan '. Maaf soal itu.
nightlyop

20

Ini adalah bagaimana Anda dapat melakukannya dengan ES6:

className = {`
      text-right
      ${itemId === activeItemId ? 'active' : ''}
      ${anotherProperty === true ? 'class1' : 'class2'}
`}

Anda dapat membuat daftar beberapa kelas dan ketentuan dan juga Anda bisa menyertakan kelas statis. Tidak perlu menambahkan perpustakaan tambahan.

Semoga berhasil ;)


2
Ini menghasilkan HTML yang sangat jelek, mengingat semua spasi tambahan.
Nakedible

2
Tidak perlu ditulis seperti itu. Ini hanyalah contoh yang lebih baik menjelaskan solusinya. Dan selalu dalam produksi, Anda memiliki versi minified :)
Hristo Eftimov

18

Vanilla JS

Tidak perlu perpustakaan eksternal - cukup gunakan string template ES6 :

<i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>

Vanilla JS BUKAN ES6. Tapi saya suka contoh Anda.
RyanNerd

8
@RyanNerd Maksud Anda "ES6 bukan vanilla JS"? Lagi pula, itu karena vanilla js berarti javascript tanpa kerangka kerja. ES6 adalah versi javascript yang lebih baru. - stackoverflow.com/a/20435685/5111113
Huw Davies

Bukan jawaban yang salah tetapi bisa banyak diperbaiki. Misalnya, semua orang menambahkan contoh tentang status.
JGallardo

10

Mungkin classnames dapat membantu Anda.

var classNames = require('classnames');
classNames('foo', {'xx-test': true, bar: false}, {'ox-test': false}); // => 'foo xx-test'

1
Bisakah Anda menjadikan contoh ini lebih bermanfaat.
JGallardo

9

Saya tidak berpikir kita perlu menggunakan paket eksternal hanya dengan menambahkan beberapa kelas.

Saya pribadi menggunakan

<li className={`li active`}>Stacy</li>

atau

<li className={`li ${this.state.isActive ? 'active' : ''}`}>Stacy<li>

yang kedua jika Anda perlu menambah atau menghapus kelas secara kondisional.


1
ini hanya akan menambah satu kelas saja.
TrickOrTreat

6

Hanya dengan menambahkan, kita dapat memfilter string kosong.

className={[
    'read-more-box',
    this.props.className,
    this.state.isExpanded ? 'open' : 'close',
].filter(x => !!x).join(' ')}

6

Anda dapat membuat elemen dengan beberapa nama kelas seperti ini, saya sudah mencoba keduanya, ini berfungsi dengan baik ...

Jika Anda mengimpor css maka Anda dapat mengikuti cara ini: Cara 1:

import React, { Component, PropTypes } from 'react';
import csjs from 'csjs';
import styles from './styles';
import insertCss from 'insert-css';
import classNames from 'classnames';
insertCss(csjs.getCss(styles));
export default class Foo extends Component {
  render() {
    return (
      <div className={[styles.class1, styles.class2].join(' ')}>
        { 'text' }
      </div>
    );
  }
}

cara 2:

import React, { Component, PropTypes } from 'react';
import csjs from 'csjs';
import styles from './styles';
import insertCss from 'insert-css';
import classNames from 'classnames';
insertCss(csjs.getCss(styles));
export default class Foo extends Component {
  render() {
    return (
      <div className={styles.class1 + ' ' + styles.class2}>
        { 'text' }
      </div>
    );
  }
}

**

Jika Anda menerapkan css sebagai internal:

const myStyle = {
  color: "#fff"
};

// React Element using Jsx
const myReactElement = (
  <h1 style={myStyle} className="myClassName myClassName1">
    Hello World!
  </h1>
);

ReactDOM.render(myReactElement, document.getElementById("app"));
.myClassName {
  background-color: #333;
  padding: 10px;
}
.myClassName1{
  border: 2px solid #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.production.min.js"></script>
<div id="app">
  
</div>


6

Anda dapat melakukan hal berikut:

<li key={index} className={`${activeClass} ${data.class} main-class`}></li>

Solusi singkat dan sederhana, semoga ini membantu.



4

Terlambat ke pesta, tapi mengapa menggunakan pihak ketiga untuk masalah sesederhana itu?

Anda bisa melakukannya seperti yang disebutkan oleh @Huw Davies - cara terbaik

1. <i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>
2. <i className={[styles['foo-bar-baz'], 'fa fa-user', 'fa-2x'].join(' ')}

Keduanya bagus. Tetapi menulis bisa menjadi rumit untuk aplikasi besar. Untuk membuatnya optimal, saya melakukan hal yang sama di atas tetapi memasukkannya ke dalam kelas pembantu

Menggunakan fungsi pembantu saya di bawah ini, memungkinkan saya untuk menjaga logika terpisah untuk pengeditan di masa depan, dan juga memberi saya beberapa cara untuk menambahkan kelas

classNames(styles['foo-bar-baz], 'fa fa-user', 'fa-2x')

atau

classNames([styles['foo-bar-baz], 'fa fa-user', 'fa-2x'])

Ini adalah fungsi pembantu saya di bawah ini. Saya telah memasukkannya ke dalam helper.js di mana saya menyimpan semua metode umum saya. Menjadi fungsi yang sangat sederhana, saya menghindari menggunakan pihak ke-3 untuk menjaga kontrol

export function classNames (classes) {
    if(classes && classes.constructor === Array) {
        return classes.join(' ')
    } else if(arguments[0] !== undefined) {
        return [...arguments].join(' ')
    }
    return ''
}

3

Anda dapat menggunakan array dan kemudian bergabung dengan mereka menggunakan ruang.

<li key={index} className={[activeClass, data.class, "main-class"].join(' ')}></li>

Ini akan menghasilkan:

<li key={index} class="activeClass data.class main-class"></li>

3

Saya tahu ini adalah jawaban yang terlambat, tetapi saya harap ini akan membantu seseorang.

Pertimbangkan bahwa Anda telah mendefinisikan kelas berikut dalam file css ' primer ', ' font-i ', ' font-xl '

  • Langkah pertama adalah mengimpor file CSS.
  • Kemudian

<h3 class = {` ${'primary'} ${'font-i'} font-xl`}> HELLO WORLD </h3>

akan melakukan trik!

Untuk info lebih lanjut: https://www.youtube.com/watch?v=j5P9FHiBVNo&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=20


3

untuk menambahkan lebih banyak kelas

... className={`${classes.hello} ${classes.hello1}`...

2

Menggunakan contoh TodoTextInput.js facebook

render() {
    return (
      <input className={
        classnames({
          edit: this.props.editing,
          'new-todo': this.props.newTodo
        })}
        type="text"
        placeholder={this.props.placeholder}
        autoFocus="true"
        value={this.state.text}
        onBlur={this.handleBlur}
        onChange={this.handleChange}
        onKeyDown={this.handleSubmit} />
    )
  } 

menggantikan classnames dengan kode plain vanilla js akan terlihat seperti ini:

render() {
    return (
      <input
        className={`
          ${this.props.editing ? 'edit' : ''} ${this.props.newTodo ? 'new-todo' : ''}
        `}
        type="text"
        placeholder={this.props.placeholder}
        autoFocus="true"
        value={this.state.text}
        onBlur={this.handleBlur}
        onChange={this.handleChange}
        onKeyDown={this.handleSubmit} />
    )
  }

2

Jika Anda tidak ingin mengimpor modul lain, fungsi ini berfungsi seperti classNamesmodul.

function classNames(rules) {
    var classes = ''

    Object.keys(rules).forEach(item => {    
        if (rules[item])
            classes += (classes.length ? ' ' : '') + item
    })

    return classes
} 

Anda bisa menggunakannya seperti ini:

render() {
    var classes = classNames({
        'storeInfoDiv': true,  
        'hover': this.state.isHovered == this.props.store.store_id
    })   

    return (
        <SomeComponent style={classes} />
    )
}

Mengapa menggunakan closure jika Anda bisa melakukan hal yang sama dengan peta atau mengurangi? function classNames(rules) { return Object.entries(rules) .reduce( (arr, [cls, flag]) => { if (flag) arr.push(cls); return arr }, [] ).join(" ") }
Евгений Савичев

1

Itu yang saya lakukan:

Komponen:

const Button = ({ className }) => (
  <div className={ className }> </div>
);

Komponen Panggilan:

<Button className = 'hashButton free anotherClass' />

1

Saya menggunakan React 16.6.3 dan @Material UI 3.5.1, dan dapat menggunakan array di className like className={[classes.tableCell, classes.capitalize]}

Jadi, dalam contoh Anda, berikut ini akan serupa.

<li key={index} className={[activeClass, data.class, "main-class"]}></li>

Inilah yang saya lakukan (meskipun tidak ada MUI) dan tidak berfungsi, hanya berlaku kelas satu - tidak ada peringatan atau keluhan.
Juan Lanus

1

Gunakan https://www.npmjs.com/package/classnames

impor nama class dari 'nama kelas';

  1. Dapat menggunakan beberapa kelas menggunakan koma yang dipisahkan:

    <li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>
  2. Dapat menggunakan beberapa kelas menggunakan koma yang dipisahkan dengan kondisi:

    <li className={classNames(classes.buttonArea, !nodes.length && classes.buttonAreaHidden)}>Hello World</li> 

Menggunakan array sebagai alat peraga ke classNames juga akan berfungsi, tetapi memberikan peringatan misalnya

className={[classes.tableCellLabel, classes.tableCell]}


0

Saya menggunakan paket rc-classnames .

// ES6
import c from 'rc-classnames';

// CommonJS
var c = require('rc-classnames');

<button className={c('button', {
  'button--disabled': isDisabled,
  'button--no-radius': !hasRadius
})} />

Anda dapat menambahkan kelas dalam format apa pun (Array, Object, Argument). Semua nilai kebenaran dari array atau Argumen plus kunci pada objek yang sama dengantrue digabungkan.

sebagai contoh:

ReactClassNames('a', 'b', 'c') // => "a b c"
ReactClassNames({ 'a': true, 'b': false, c: 'true' }) // => "a c"
ReactClassNames(undefined, null, 'a', 0, 'b') // => "a b"

0

I bind classNameske modul css diimpor ke dalam komponen.

import classNames from 'classnames'; 
import * as styles from './[STYLES PATH];
const cx = classNames.bind(styles); 

classnamesmemberikan kemampuan untuk mendeklarasikan classNameelemen Bereaksi dengan cara deklaratif.

ex:

<div classNames={cx(styles.titleText)}> Lorem </div>

<div classNames={cx('float-left')}> Lorem </div> // global css declared without css modules
<div classNames={cx( (test === 0) ?
             styles.titleText : 
             styles.subTitleText)}>  Lorem </div> // conditionally assign classes

<div classNames={cx(styles.titleText, 'float-left')}> Lorem </div> //combine multiple classes

0

Saya biasanya menggunakannya seperti ini: (dalam kasus Anda)

    <li  key={index} className={
        "component " +
        `${activeClass? activeClass: " not-an-active-class "}` +
        `${data.class? " " + data.class : " no-data-class "}`
   } />

Ketika datang ke JSX dan (biasanya) kami memiliki beberapa json ... daripada Anda loop itu ... komponen . map , ditambah beberapa persyaratan untuk memeriksa apakah properti json ada untuk merender nama kelas tergantung pada nilai properti dari JSON. Dalam contoh di bawah ini, component_color dan component_dark_shade adalah properti dari component.map ()

   <div className={
        "component " +
        `${component_color? component_color: " no-color "}` +
        `${component_dark_shade? " " + component_dark_shade : " light "}`
   }/>

Output: <div class="component no-color light" .... Atau: <div class="component blue dark" ....tergantung pada nilai dari peta ...


0

Ketika saya memiliki banyak kelas yang berbeda, saya telah menemukan yang berikut berguna.

Filter menghapus salah satu nullnilai dan gabungan menempatkan semua nilai yang tersisa ke dalam string yang dipisahkan spasi.

const buttonClasses = [
    "Button", 
    disabled ? "disabled" : null,
    active ? "active" : null
].filter((class) => class).join(" ")

<button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.