Reaguj: warunkowo przekazuje prop do komponentu


85

Chciałbym wiedzieć, czy istnieje lepszy sposób warunkowego przekazania właściwości niż użycie instrukcji if.

Na przykład w tej chwili mam:

var parent = React.createClass({
  propTypes: {
    editable: React.PropTypes.bool.isRequired,
    editableOpts: React.PropTypes.shape({...})
  },
  render: function() {
    if(this.props.editable) {
      return (
        <Child editable={this.props.editableOpts} />
      );
    } else {
      // In this case, Child will use the editableOpts from its own getDefaultProps()
      return (
        <Child />
      );
    }
  }
});

Czy jest sposób, aby napisać to bez instrukcji if? Zastanawiałem się nad czymś podobnym do typu instrukcji inline-if w JSX:

var parent = React.createClass({
  propTypes: {
    editable: React.PropTypes.bool.isRequired,
    editableOpts: React.PropTypes.shape({...})
  },
  render: function() {
    return (
      <Child 
        {this.props.editable ? editable={this.props.editableOpts} : null} 
      />
    );
  }
});

Podsumowując : próbuję znaleźć sposób na zdefiniowanie właściwości dla Child, ale przekazać wartość (lub zrobić coś innego), która Childnadal pobiera wartość tego właściwości z Childwłasnej getDefaultProps().


Czy możesz dołączyć kod Child? Poza tym, czy chciałeś powiedzieć <Child editableOpts={this.props.editableOpts} />zamiast <Child editable={this.props.editableOpts} />?
Jim Skerritt

@JimSkerritt Nie pomyliłem rekwizytów, chociaż wiem, że tak wygląda. Próbuję użyć react-bootstrap-tablei to jest format, którego używają. Nie jestem pewien, czy Childkod faktycznie ma znaczenie dla tego, o co pytam, dlatego go nie uwzględniłem. Naprawdę szukam sposobu, aby opcjonalnie przekazać lub nie przekazać rekwizytu Child, który nie wymaga posiadania ogromnej ilości podobnego kodu w instrukcjach if w Parent.
Matthew Herbst

1
Rozumiem, tylko sprawdzam :) Niedługo będę miał dla ciebie odpowiedź
Jim Skerritt

Odpowiedzi:


151

Byłeś blisko swojego pomysłu. Okazuje się, że przekazanie undefinedwłaściwości jest równoznaczne z nieuwzględnianiem jej w ogóle, co nadal będzie wywoływać domyślną wartość właściwości. Możesz więc zrobić coś takiego:

var parent = React.createClass({
  propTypes: {
    editable: React.PropTypes.bool.isRequired,
    editableOpts: React.PropTypes.shape({...})
  },
  render: function() {
    return <Child 
      editable={this.props.editable ?
                  this.props.editableOpts : 
                  undefined}
    />;
  }
});

Oh niesamowite! Czy znalazłeś to gdzieś w dokumentacji? Szukałem tego, ale nie mogłem nic znaleźć podczas szybkiego wyszukiwania
Matthew Herbst

nie jestem pewien, czy jest to w dokumentacji, czy nie, po prostu coś, czego nauczyłem się podczas korzystania z Reacta :)
Jim Skerritt

10
nullnie jest uzbrojony w taką moc jak undefinedBTW.
Sezon

3
przydatna sztuczka! Żałuję, że nie ma dobrych zasobów na temat skutecznego korzystania z technik renderowania warunkowego
nicodjimenez

1
W falseprzypadku, gdy nie działa to tak, jak chciałem - nadal otrzymuję parę klucz-wartość property:: null. Czy nadal można to jakoś zrobić za pomocą pojedynczego elementu JSX?
Gal Grünfeld

29

Dodaj operator spreadu do this.props.editable:

<Child {...(this.props.editable ? {editable: {this.props.editableOpts}} : {})} >

powinno działać.


1
Czy to nie daje takiego samego wyniku, jak editable = {this.props.editable? this.props.editableOpts: undefined} Czy jest jakaś różnica?
garyee

1
@garyee: różnica polega na tym, że niektóre komponenty mogą niepoprawnie traktować undefinedjako nadpisanie (na przykład null, które jest zawsze przesłonięciem), więc jedynym sposobem na zachowanie wartości domyślnej zamiast ustawiania jej na fałszywą wartość jest jawne jej nieprzekazywanie, nieprzekazywanie undefined.
Yann Dìnendal

@ YannDìnendal co, jeśli użyję pustego obiektu zamiast niezdefiniowanego, na przykład <Child {... (this.props.editable? {Editable: {this.props.editableOpts}}: {)}> Czy to ma znaczenie? który jest lepszy?
sktguha

1
@sktguha: tak, rzeczywiście, wygląda na literówkę Myślę: nie możemy rozprzestrzeniać undefined, więc tak, powinno to być {}na końcu.
Zaproponuję

18

Zdefiniuj propszmienną:

let props = {};
if (this.props.editable){
  props.editable = this.props.editable;
}

A potem użyj go w JSX:

<Child {...props} />

Oto rozwiązanie w Twoim kodzie:

var parent = React.createClass({
  propTypes: {
    editable: React.PropTypes.bool.isRequired,
    editableOpts: React.PropTypes.shape({...})
  },
  render: function() {
    let props = {};
    if (this.props.editable){
      props.editable = this.props.editable;
    }
    return (
      <Child {...props} />
    );
  }
});

Źródło, dokumentacja React: https://facebook.github.io/react/docs/jsx-in-depth.html#spread-attributes


Podoba mi się to rozwiązanie. Chciałbym childPropsjednak uniknąć nieporozumień
Daniel Reina

4

Właściwie, jeśli twoja prop jest logiczna, nie jest potrzebna do implementacji warunku, ale jeśli chcesz dodać rekwizyt przez warunek w linii, powinieneś napisać jak poniżej:

const { editable, editableOpts } = this.props;
return (
  <Child {...(editable && { editable: editableOpts } )} />
);

Mam nadzieję, że to cię nie zmyli. to {...oznacza, że jest operator spread jak przepływające istniały rekwizyty: {...props}i editable &&środków, jeśli editablejest obiekt pozwoli i zrobimy nowy obiekt podoba: to znaczy, że jednak jeśli jest to prawdą.true{ editable: editableOpts }{...{...{ editable: editableOpts }}editable={editableOpts}this.porps.editable


0
var parent = React.createClass({
  propTypes: {
    editable: React.PropTypes.bool.isRequired,
    editableOpts: React.PropTypes.shape({...})
  },
  render: function() {
    return (
      <Child 
        {...(this.props.editable && {editable=this.props.editableOpts})} 
      />
    );
  }
});

Spowoduje to przekazanie właściwości, jeśli są zdefiniowane. W przeciwnym razie rekwizyty nie są przekazywane. W drugiej odpowiedzi rekwizyty są nadal przekazywane, ale wartość jest taka, undefinedktóra nadal oznacza, że ​​rekwizyty są przekazywane.


1
Przejście undefineddo rekwizytu jest równoznaczne z nieprzekazywaniem go wcale.
Matthew Herbst

Tak, rozumiem. Chciałem tylko, żeby było jasne! Dzięki!
sanair96

0

możesz też spróbować tej krótkiej ręki

 <Child {...(this.props.editable  && { editable: this.props.editableOpts })} />
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.