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().

Matthew Herbst
źródło
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}
    />;
  }
});
Jim Skerritt
źródło
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ć.

Jamal Hussain
źródło
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

Leon Gilyadov
źródło
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

AmerllicA
źródło
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.

sanair96
źródło
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 })} />
mortezashojaei
źródło