Co to znaczy… odpocznij w React JSX


83

Patrząc na ten przykład React Router Dom v4 https://reacttraining.com/react-router/web/example/auth-workflow , widzę, że komponent PrivateRoute niszczy taką propozycję resztową

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    fakeAuth.isAuthenticated ? (
      <Component {...props}/>
    ) : (
      <Redirect to={{
        pathname: '/login',
        state: { from: props.location }
      }}/>
    )
  )}/>
)

Chcę mieć pewność, że { component: Component, ...rest }oznacza to:

From props, pobierz właściwość Component, a następnie wszystkie inne właściwości, które otrzymałeś, i zmień nazwę propsna, restaby uniknąć problemów z nazywaniem właściwości przekazywanych do renderfunkcji Route

Czy mam rację?


5
Jest to niestandaryzowana, ale składnia zdefiniowana na github.com/tc39/proposal-object-rest-spread
zerkms

Odpowiedzi:


156

Przepraszam, zdałem sobie sprawę, że moja pierwsza odpowiedź (miejmy nadzieję, że nadal dostarcza użytecznego / dodatkowego kontekstu) nie odpowiada na twoje pytanie. Pozwól mi spróbować jeszcze raz.

Ty pytasz:

Chcę być tego pewien { component: Component, ...rest } oznacza to:

Od props, weź właściwość, Componenta następnie wszystkie inne propsdane, i zmień nazwę propsna, restaby uniknąć problemów z nazewnictwem z propsprzekazaną do renderfunkcji Route

Twoja interpretacja nie jest całkiem poprawna. Opierając się jednak na twoich przemyśleniach, wydaje się, że przynajmniej jesteś świadomy faktu, że to, co się tutaj dzieje, sprowadza się do pewnego rodzaju destrukcji obiektu (więcej wyjaśnień znajdziesz w drugiej odpowiedzi i komentarzach).

Aby dać dokładne wyjaśnienie, podzielmy { component: Component, ...rest }wyrażenie na dwie oddzielne operacje:

  1. Operacja 1: Znajdź componentwłaściwość określona na props( Uwaga : mała litera c omponent) i przypisać go do nowej lokalizacji w stanie nazwać Component( Uwaga : kapitał C omponent).
  2. Operacja 2: Następnie weź wszystkie pozostałe właściwości zdefiniowane w propsobiekcie i zbierz je wewnątrz argumentu o nazwie rest.

Ważne jest to, że NIE zmieniasz nazwy propsna rest. (Nie ma też nic wspólnego z próbą „uniknięcia problemów z nazewnictwem w przypadku propsprzekazywania do renderfunkcji Route ”).

rest === props;
// => false

Po prostu pobierasz resztę (stąd dlaczego argument jest tak nazwany) właściwości zdefiniowanych w twoim propsobiekcie do nowego argumentu o nazwie rest.


Przykładowe użycie

Oto przykład. Załóżmy, że mamy obiekt `myObj` zdefiniowany następująco:
const myObj = {
  name: 'John Doe',
  age: 35,
  sex: 'M',
  dob: new Date(1990, 1, 1)
};

W tym przykładzie warto pomyśleć o propstym, że ma taką samą strukturę ( tj. Właściwości i wartości), jak pokazano w myObj. Teraz napiszmy następujące zadanie.

const { name: Username, ...rest } = myObj

Powyższe stwierdzenie sprowadza się zarówno do deklaracji, jak i przypisania dwóch zmiennych (lub, jak sądzę, stałych). Stwierdzenie to można sobie wyobrazić jako:

Weź właściwość namezdefiniowaną na myObji przypisz jej wartość do nowej zmiennej, którą wywołujemy Username. Następnie podejmuje wszelkie inne właściwości zostały określone na myObj( czyli , age, sexi dob) i zebrać je do nowego obiektu przypisanego do nazwy zmiennej my rest.

Logowanie Usernamei restdo consolepotwierdzą to. Mamy następujące:

console.log(Username);
// => John Doe
console.log(rest);
// => { age: 35, sex: 'M', dob: Mon Jan 01 1990 00:00:00 GMT-0800 (PST) }

Dygresja

Możesz się zastanawiać:

Po co kłopotać się ściąganiem componentnieruchomości tylko po to, by zmienić jej nazwę Componentna wielką literę „C”?

Tak, wydaje się to dość trywialne. I chociaż jest to standardowa praktyka Reacta, jest powód, dla którego cała dokumentacja Facebooka dotycząca jego frameworku jest napisana jako taka. Mianowicie, kapitalizowanie niestandardowych komponentów renderowanych za pomocą JSX jest mniej praktyką samą w sobie, niż koniecznością. Reaguj, a właściwie, JSX rozróżnia wielkość liter . Komponenty niestandardowe wstawione bez wielkiej pierwszej litery nie są renderowane w modelu DOM. Tak właśnie zdefiniował się React, aby identyfikować niestandardowe komponenty. Tak więc, gdyby nie przykład dodatkowo przemianowany na componentwłasność, że oderwano od propsdo ComponentThe <component {...props} />wyrażenie nie powiedzie się poprawnie renderowania.


5
świetna eksploracja dla nas, noobów!
user2763557

13

Pozwala ci to „rozłożyć” wszystko propsjednym zwięzłym wyrażeniem. Na przykład załóżmy, że propsotrzymany przez Twój PrivateRoutekomponent wygląda jak

// `props` Object:
{
  thing1: 'Something',
  thing2: 'Something else'
}

Jeśli chciał dalszego strony od tych pozycji ( tj , thing1i thing2) w dół do zagnieżdżonych <Component />znaczników i nie byli zaznajomieni z przedmiotem spread składni, można napisać:

<Component
  thing1={ props.thing1 }
  thing2={ props.thing2 } />

Jednak { ...props }składnia zapobiega takiej szczegółowości, pozwalając, aby szerzyć swój propsprzedmiot w tej samej Jednym ze sposobów może rozprzestrzeniać tablicę wartości ( np , [...vals]). Innymi słowy, wyrażenie JSX poniżej i powyżej są dokładnie równoważne.

<Component { ...props } />

1
Chociaż jest to powiązane, nie mieszaj składni spreadu JSX z właściwościami reszt .
Felix Kling

3
„Pozwala na„ rozłożenie ”wszystkich rekwizytów w jednym zwięzłym wyrażeniu”. To nie tak. ...restin { component: Component, ...rest } zbiera wszystkie inne właściwości obiektu rest. Pytanie dotyczy ...rest, a nie{...props}
Felix Kling

Jak zauważa Felix, istnieje rozróżnienie między (niestandardowym) operatorem rozprzestrzeniania obiektów w JSX a pozostałym operatorem rozszerzania _ / _ zdefiniowanym w specyfikacji ECMAScript 2015. Po pierwsze, próba napisania czegoś takiego jak { ...myObj }w środowisku innym niż React ( np. W konsoli przeglądarki) spowoduje wyświetlenie pliku SyntaxError. Niemniej jednak, rozpiętość reszt _ / _ w ES6 zapewnia użyteczne ramy koncepcyjne, w których można myśleć o rozprzestrzenianiu się obiektów JSX .
IsenrichO

4

Upraszczajmy: w JavaScript, jeśli pary „klucz: wartość” są takie same, obj={account:account}to to samo co obj={account}. Więc podczas przekazywania rekwizytów z komponentu rodzica do komponentu potomnego:

const Input = ({name,label,error, ...rest}) => {
  return (
    <div className="form-group">
      <label htmlFor={name}>{label}</label>
      <input
        {...rest}
        autoFocus
        name={name}
        id={name}
        className="form-control"
        aria-describedby="emailHelp"
      />
    </div>
  );
};
export default Input;

resztę rekwizytów będziesz przekazywać jako:

label={label} placeholder={placeholder} type={type}
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.