Poprawny sposób obsługi stylów warunkowych w Reakcie


93

Robię teraz trochę Reacta i zastanawiałem się, czy istnieje „poprawny” sposób na stylizację warunkową. W samouczku używają

style={{
  textDecoration: completed ? 'line-through' : 'none'
}}

Wolę nie używać stylów wbudowanych, więc zamiast tego chcę używać klasy do sterowania stylami warunkowymi. Jak można podejść do tego w myśleniu Reacta? A może powinienem po prostu użyć tego wbudowanego sposobu stylizacji?


1
Myślę, że możesz mieć reduxi być reactzdezorientowanym. Redux nie ma nic wspólnego ze stylizacją.
rossipedia

3
myślę, że twoje preferencje są trafne w przypadku dokumentów, ale są zbyt gorliwe w przypadku aplikacji, w których kompatybilność z wymianą znaczników nie jest ważna. Niektóre główne aplikacje internetowe faktycznie pozbywają się klas i używają tylko stylu wbudowanego, który jest bardziej przewidywalny i łatwiejszy do zrozumienia niż to, która z 5 zastosowanych reguł powoduje pogrubienie tekstu. gdy atrybuty są dynamiczne, nie oszczędzasz dużo przepustowości, jak w przypadku powtarzających się dokumentów. semantyka aplikacji (znaczniki widoku źródła) też nie są tak ważne ...
dandavis

@rossipedia ah tak, dziękuję, pomyliłem się, patrząc na tutorial Redux, myśląc o tym, dziękuję!
davidhtien

Jeśli nie jesteś pewien, jaka będzie wartość dekoracji tekstu ze względu na kaskadę, a chcesz zastosować przejście liniowe tylko wtedy, gdy wypełnienie jest prawdziwe, musisz zbudować obiekt stylu. W ten sposób nie ustawiasz jej na none przypadkowo, gdy była to inna wartość. const style = {} if (complete) {style ['textDecoration'] = 'line-through'}
Edward,

Odpowiedzi:


78

Jeśli wolisz używać nazwy klasy, koniecznie używaj nazwy klasy.

className={completed ? 'text-strike' : null}

Pomocny może być również pakiet nazw klas . Dzięki niemu Twój kod wyglądałby następująco:

className={classNames({ 'text-strike': completed })}

Nie ma „poprawnego” sposobu na stylizację warunkową. Rób wszystko, co jest dla Ciebie najlepsze. Osobiście wolę unikać stylizacji wbudowanej i używać klas w sposób właśnie opisany.

POSTSCRIPT [06-AUG-2019]

Chociaż pozostaje prawdą, że React nie ma opinii na temat stylizacji, obecnie polecam rozwiązanie CSS-in-JS; mianowicie stylizowane elementy lub emocje . Jeśli nie znasz jeszcze Reacta, na początek trzymaj się klas CSS lub stylów wbudowanych. Ale kiedy już poczujesz się dobrze z Reactem, polecam zaadoptowanie jednej z tych bibliotek. Używam ich w każdym projekcie.


Hej, jeśli zdecydujesz się użyć className jako metody stylizacji warunkowej. Bez classNames lib. Radzę używać undefinedzamiast null. classNameNieruchomość przyjmuje jako wejście Wpisz łańcuch lub undefined - typ (String | niezdefiniowany) - ⚡️
0xx

3
@JadRizk jeszcze lepszym podejściem jest nie ustawianie nazwy klasy, jeśli nie masz prawidłowej wartości do ustawienia. const attrs = completed?{className:'text-strike'}:{}następnie <li {...attrs}>text to maybe strike</li>(operator rozproszenia). W ten sposób w ogóle nie ustawiasz className, chyba że masz dobrą wartość do przypisania. Jest to ważne podejście do ustawiania niektórych stylów wbudowanych, w przypadku których nie możesz wiedzieć, jaka jest bieżąca wartość (ponieważ może być ustawiona przez CSS w pliku, nad którym możesz nie kontrolować).
LinuxDisciple,

@LinuxDisciple, jeśli wszystkie pola dają wynik falsey, po classnamesprostu zwraca pusty ciąg. Żaden CSS nie wpłynie na to.
David L. Walsh,

@ DavidL.Walsh 21 godzin temu Myślałem, że rozwiązanie JadRizk było fałszywym wyborem pomiędzy, nulla undefinedto nadal skutkowałoby brakiem wartości classatrybutu w html (tj. <p class></p>Zamiast <p></p>), więc dostarczyłem metodę, która classNamew ogóle pozwala uniknąć ustawiania . Tak się składa, że ​​myliłem się co do rozwiązania JadRizk. W przypadku podanego problemu uważam, że twoje rozwiązanie z udoskonaleniem JadRizk jest najlepsze. Moja składnia może warunkowo ustawić dowolną listę właściwości i ich wartości, ale samo ustawienie nazwy klasy jest przesadą.
LinuxDisciple,

106
 <div style={{ visibility: this.state.driverDetails.firstName != undefined? 'visible': 'hidden'}}></div>

Sprawdź powyższy kod. To wystarczy.


3
Dokładnie szukałem czegoś takiego. Stylizacja warunkowa, dziękuję.
Souvik Ghosh

<div style = {{visibility: this.state.driverDetails.firstName! == undefined? 'widoczny': 'ukryty'}}> </div>. Mała literówka w ==.
vinayak shahdeo

31

Jeśli musisz warunkowo zastosować style wbudowane (zastosuj wszystko lub nic), ta notacja również działa:

style={ someCondition ? { textAlign:'center', paddingTop: '50%'} : {}}

W przypadku niespełnienia warunku „someCondition” przekazujesz pusty obiekt.


2
Czy ten wzorzec nie tworzy jednak niepotrzebnej różnicy? Moje rozumienie różnic w DOM jest takie, że styleprop tutaj zawsze się zmienia, ponieważ w Javascript {} != {} Jeśli mam rację co do różnicowania, być może lepiej jest użyć " undefined" zamiast " {}"
Dawson B

1
Dobra notatka. Nie jestem tego pewien.
Vlado

8

Po pierwsze, zgadzam się z tobą ze względu na styl - również (i również stosuję) warunkowo stosowałbym klasy, a nie style wbudowane. Ale możesz użyć tej samej techniki:

<div className={{completed ? "completed" : ""}}></div>

Aby uzyskać bardziej złożone zestawy stanów, zbierz tablicę klas i zastosuj je:

var classes = [];

if (completed) classes.push("completed");
if (foo) classes.push("foo");
if (someComplicatedCondition) classes.push("bar");

return <div className={{classes.join(" ")}}></div>;

6

zamiast tego:

style={{
  textDecoration: completed ? 'line-through' : 'none'
}}

możesz spróbować wykonać następujące czynności, używając krótkich obwodów:

style={{
  textDecoration: completed && 'line-through'
}}

https://codeburst.io/javascript-short-circuit-conditionals-bbc13ac3e9eb

kluczowe informacje z linku:

Zwarcie oznacza, że ​​w JavaScript, gdy obliczamy wyrażenie AND (&&), jeśli pierwszy operand jest fałszywy, JavaScript spowoduje zwarcie i nawet nie spojrzy na drugi operand.

Warto zauważyć, że zwróci to wartość false, jeśli pierwszy operand jest fałszywy, więc może być konieczne rozważenie, jak wpłynie to na twój styl.

Inne rozwiązania mogą być lepszą praktyką, ale pomyślałem, że warto się nimi podzielić.


3

Inny sposób, używając stylu wbudowanego i operatora spreadu

style={{
  ...completed ? { textDecoration: completed } : {}
}}

W ten sposób przydaje się w niektórych sytuacjach, w których chcesz dodać kilka właściwości w tym samym czasie na podstawie warunku.


1
Niezłe podejście, jeśli nie chcesz zmieniać domyślnego stylu
dhilt

2

Natknąłem się na to pytanie, próbując odpowiedzieć na to samo pytanie. Podejście McCrohana do klas array & join jest solidne.

Dzięki mojemu doświadczeniu pracowałem z wieloma starszymi kodami ruby, które są konwertowane do Reacta, a kiedy budujemy komponenty, sięgam po istniejące klasy css i style wbudowane.

przykładowy fragment w komponencie:

// if failed, progress bar is red, otherwise green 
<div
    className={`progress-bar ${failed ? failed' : ''}`}
    style={{ width: this.getPercentage() }} 
/>

Ponownie sięgam po starszy kod CSS, „pakuję” go w komponent i przechodzę dalej.

Więc naprawdę czuję, że jest trochę w powietrzu, co jest „najlepsze”, ponieważ ta etykieta będzie się znacznie różnić w zależności od twojego projektu.


Nie należy łączyć nazw klas z atrybutem stylu, to trochę bałagan
Sebastian Voráč

0

Najlepszym sposobem obsługi stylu jest użycie klas z zestawem właściwości css.

przykład:

<Component className={this.getColor()} />

getColor() {
    let class = "badge m2";
    class += this.state.count===0 ? "warning" : danger;
    return class;
}

0

Możesz użyć czegoś takiego.

render () {
    var btnClass = 'btn';
    if (this.state.isPressed) btnClass += ' btn-pressed';
    else if (this.state.isHovered) btnClass += ' btn-over';
    return <button className={btnClass}>{this.props.label}</button>;
  }

Możesz też użyć pakietu NPM nazw klas, aby uprościć pracę z dynamicznymi i warunkowymi właściwościami className (szczególnie bardziej niż warunkowe manipulowanie ciągami znaków).

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.