Reaguj J warunkowo stosując atrybuty klasy

333

Chcę warunkowo wyświetlić i ukryć tę grupę przycisków w zależności od tego, co jest przekazywane z komponentu nadrzędnego, który wygląda następująco:

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

Nic się jednak nie dzieje z {this.props.showBulkActions? 'Pokaż ukryte'}. Czy robię tu coś złego?

apexdodge
źródło
Możesz również rozważyć użycie opcji ładowania początkowego , ponieważ to abstrakuje niektóre elementy klasy we właściwościach składników, dzięki czemu to, co próbujesz zrobić, jest nieco łatwiejsze.
Dancrumb

Odpowiedzi:

588

Nawiasy klamrowe znajdują się wewnątrz ciągu, więc jest on oceniany jako ciąg. Muszą być na zewnątrz, więc to powinno działać:

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

Zwróć uwagę na spację po „przeciągnięciu w prawo”. Nie chcesz przypadkowo podać klasy „pull-righthow” zamiast „pull-right show”. Tam też muszą być nawiasy.

spitfire109
źródło
3
Dzięki! Musiałem go nieco zmodyfikować, ponieważ z jakiegoś powodu w ogóle nie wyświetlało się w prawo btn-group. Po prostu pokaż lub ukryj.
apexdodge
Jest to szczególnie pomocne w niektórych przypadkach, w których classnamesmoże nie być właściwe. Jeśli jesteś w swojej renderfunkcji i masz map, możesz wiedzieć tylko, czy chcesz dodać klasę podczas jej renderowania, więc ta odpowiedź jest do tego bardzo przydatna.
Dave Cooper
świetna alternatywa zamiast posiadania zestawu szablonów warunkowych w renderowaniu lub powrocie
devonj
@apexdodge, jaką modyfikację musiałeś wykonać. Mam ten sam problem.
RamY
1
@RamY Jednym ze sposobów jest umieszczenie wszystkich klas w warunkowym this.props.showBulkActions ? 'btn-group pull-right show' : 'btn-group pull-right hidden'). Nie elegancki, ale działa.
Ian
87

Jak skomentowali inni, narzędzie classnames jest obecnie zalecanym podejściem do obsługi warunkowych nazw klas CSS w ReactJs.

W twoim przypadku rozwiązanie będzie wyglądać następująco:

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

...

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

Na marginesie, sugeruję, abyś starał się unikać używania obu klas showi hiddenklas, aby kod był prostszy. Najprawdopodobniej nie musisz ustawiać klasy, aby coś pokazywało się domyślnie.

Diego V.
źródło
11
Czy mógłbyś rozwinąć narzędzie classNames będące „obecnie zalecanym podejściem”? Czy jest to zapisane gdzieś w dobrze cenionym dokumencie najlepszych praktyk? A może po prostu słowo mówione wokół React i classNamesw tej chwili?
Alexander Nied
6
@ towarzyszył W momencie pisania tego dokumentu był zalecany w oficjalnej dokumentacji React: web.archive.org/web/20160602124910/http://facebook.github.io:80/…
Diego V
3
W najnowszej dokumentacji wciąż wspomniano : „ Jeśli często piszesz taki kod, pakiet classnames może go uprościć
Franklin Yu
66

Jeśli używasz transpilatora (takiego jak Babel lub Traceur), możesz użyć nowych „ ciągów szablonów ” ES6 .

Oto odpowiedź @ spitfire109, odpowiednio zmodyfikowana:

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

Takie podejście pozwala na wykonywanie schludne rzeczy tak, rendering albo s-is-shownalbo s-is-hidden:

<div className={`s-${this.props.showBulkActions ? 'is-shown' : 'is-hidden'}`}>
Bertrand
źródło
20
Zachowaj ostrożność przy drugim podejściu, szczególnie w dużych bazach kodowych, ponieważ powoduje to, że łańcuchy klas są mniej zrozumiałe. Na przykład, jeśli ktoś szuka s-is-shownlub s-is-hiddenw bazie kodu, nie znajdzie tego kodu.
zaznacz
15

Możesz użyć tutaj literałów ciągowych

const Angle = ({show}) => {

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

   return <i className={angle} />
}
Musa
źródło
9

Spoglądając na dobrą odpowiedź @ spitfire109, można zrobić coś takiego:

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

  return names.join(' ');
}

a następnie w ramach funkcji renderowania:

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

utrzymuje jsx krótki

łuskowaty
źródło
8

Lub użyj nazw klas npm . Jest to bardzo łatwe i przydatne, zwłaszcza przy tworzeniu listy klas

Ołówek
źródło
8

Jeśli potrzebujesz tylko jednej opcjonalnej nazwy klasy:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? "show" : "")}>
Eugene Chybisov
źródło
1
To doda falseklasę, gdy warunek się nie powiedzie.
RA.
6

Możesz używać tablic ES6 zamiast nazw klas. Odpowiedź oparta jest na artykule dr Axela Rauschmayera: Warunkowo dodawanie wpisów do tablicy i literałów obiektowych .

<div className={[
                 "classAlwaysPresent", 
                 ...Array.from(condition && ["classIfTrue"])
                ].join(" ")} />
Tudor Morar
źródło
proszę rozwinąć, co to jest warunek?
mibbit
const warunek = (1 === 1);
Tudor Morar,
5

2019:

React jest jezioro wiele narzędzi. Ale nie potrzebujesz npmdo tego żadnej paczki. po prostu stwórz gdzieś funkcję classnamesi wywołaj ją, kiedy będziesz potrzebować;

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

lub

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

przykład

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

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

Tylko dla inspiracji

Element stwierdzenie pomocniczych i wykorzystywane togglemetody

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

przykład:

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

function classstate(obj){
  for( let n in obj) classes.toggle(n,obj[n]);
 return classes; 
}
pery mimon
źródło
4

Bardziej eleganckie rozwiązanie, które jest lepsze pod względem konserwacji i czytelności:

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

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

<Element className={classNames.join(' ')}/>
Nate Ben
źródło
3

możesz użyć tego:

<div className={"btn-group pull-right" + (this.props.showBulkActions ? ' show' : ' hidden')}>
AmirBll
źródło
2

To by działało dla ciebie

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

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

return (
            ...
            <div className={_myClasses}>
               ...
            </div>
    );
  }
});
Manoj Amalraj
źródło
1

Możesz użyć tego pakietu npm. Obsługuje wszystko i ma opcje klas statycznych i dynamicznych opartych na zmiennej lub funkcji.

// 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
źródło
1

W this.props.showBulkActionszależności od wartości możesz dynamicznie przełączać klasy w następujący sposób.

<div ...{...this.props.showBulkActions 
? { className: 'btn-group pull-right show' } 
: { className: 'btn-group pull-right hidden' }}>
Vladimir Trifonov
źródło
1

Chciałbym dodać, że możesz również używać zmiennej treści jako części klasy

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

Kontekstem jest rozmowa między botem a użytkownikiem, a style zmieniają się w zależności od nadawcy, oto wynik przeglądarki:

<img src="http://imageurl" alt="Avatar" class="img-bot">
JC
źródło
1

Jest to przydatne, gdy masz więcej niż jedną klasę do dołączenia. Możesz dołączyć do wszystkich klas w tablicy ze spacją.

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

Zastąpić:

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

z:

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}
Amit Agarwal
źródło
0

Odniesienie do odpowiedzi ogniowej @split, możemy ją zaktualizować o literały szablonów, które są bardziej czytelne, dla odniesienia Literatura szablonu javascript

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}>
Achil Aravind
źródło
0

Znalazłem to, co wyjaśnia, jak to zrobić za pomocą trójki i Biblioteki Classnames

chachan
źródło