Що це означає ... відпочинок у React JSX


82

Дивлячись на цей приклад React Router Dom v4 https://reacttraining.com/react-router/web/example/auth-workflow, я бачу, що компонент PrivateRoute деструктурує такий репер, як цей

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

Я хочу бути впевненим, що це { component: Component, ...rest }означає:

З props, отримати компонент пропелер , а потім всі інші реквізити , дані вам, і перейменуйте propsдо restтак що ви можете уникнути імен проблем з реквізитом , переданим Маршрут renderфункції

Я правий?


5
Це нестандартизований ще синтаксис, визначений на github.com/tc39/proposal-object-rest-spread
zerkms

Відповіді:


156

На жаль, я зрозумів, що моя перша відповідь (хоча, сподіваюся, все ще надає корисний / додатковий контекст) не відповідає на ваше запитання. Дозвольте мені спробувати ще раз.

Ви запитаєте:

Я хочу бути впевненим, що це { component: Component, ...rest }означає:

З props, отримайте Componentпроп, а потім усі інші propsдані вам, і перейменуйте propsна, restщоб уникнути проблем з іменуванням propsпереданих renderфункції Route

Ваше тлумачення не зовсім коректне. Однак, виходячи з ваших думок, схоже, ви принаймні усвідомлюєте той факт, що те, що тут відбувається, є якоюсь деструктуризацією об’єкта (див. Другу відповідь та коментарі там для отримання додаткових роз’яснень).

Щоб дати точне пояснення, розберемо { component: Component, ...rest }вираз на дві окремі операції:

  1. Операція 1: Знайдіть componentвластивість, визначену на props( Примітка : нижній регістр c omponent), і призначте його новому розташуванню у стані, який ми називаємо Component( Примітка : велике C omponent).
  2. Операція 2: Потім візьміть усі залишені властивості, визначені в propsоб’єкті, та зберіть їх у аргументованому аргументі rest.

Важливим моментом є те, що ви НЕ перейменовуєтесь propsна rest. (І це також не пов’язано зі спробою "уникнути проблем з іменуванням propsпереданих renderфункції Route ".)

rest === props;
// => false

Ви просто витягуєте решту (отже, чому аргумент так називається) властивостей, визначених у вашому propsоб'єкті, у новий аргумент, який називається rest.


Приклад використання

Ось приклад. Припустимо, у нас є об'єкт `myObj`, визначений таким чином:
const myObj = {
  name: 'John Doe',
  age: 35,
  sex: 'M',
  dob: new Date(1990, 1, 1)
};

У цьому прикладі може допомогти просто думка про те props, що має однакову структуру ( тобто властивості та значення), як показано в myObj. Тепер напишемо наступне завдання.

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

Вищезазначене твердження відповідає як оголошенню, так і присвоєнню двох змінних (або, я думаю, константам). Заяву можна розглянути як:

Візьміть властивість, nameвизначену, myObjі призначте її значення новій змінній, яку ми викликаємо Username. Потім, візьміть будь-які інші властивості були визначені на myObj( тобто , age, sexі dob) і зібрати їх в новий об'єкт , призначений для імені змінних ми rest.

Вхід в журнал Usernameта restдо consoleпідтвердження цього. Ми маємо наступне:

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

Бічна примітка

Ви можете здивуватися:

Навіщо переживати труднощі з вилученням componentмайна, лише перейменовуючи його Componentз великої літери "С"?

Так, це здається досить дріб’язковим. І хоча це стандартна практика React, є причина, що вся документація Facebook щодо її фреймворку написана як така. А саме, використання великих літер користувальницьких компонентів, які відображаються за допомогою JSX, є меншою практикою як такою, ніж необхідністю. Реагуйте, або, більш правильно, JSX чутливий до регістру . Спеціальні компоненти, вставлені без великої першої літери, не відображаються в DOM. Саме так React визначився для ідентифікації користувацьких компонентів. Таким чином, був приклад додатково не перейменував componentвластивість, витягнуту з propsдо Component, то <component {...props} />вираз буде не правильно відображався.


5
чудове пояснення для нас, нубі!
user2763557

13

Це дозволяє "розподілити" все своє propsв одному стислому виразі. Наприклад, припустимо, що propsотриманий вашим PrivateRouteкомпонентом вигляд має такий вигляд

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

Якщо ви хочете надалі передавати ці елементи ( тобто , thing1і thing2) до вкладеного <Component />тегу, і ви не були знайомі з синтаксисом розповсюдження об’єктів, ви можете написати:

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

Тим НЕ менше, { ...props }синтаксис таких устран багатослів'я, дозволяючи поширювати свій propsоб'єкт таким же чином можна було б поширити масив значень ( наприклад , [...vals]). Іншими словами, вирази JSX, наведені нижче, і наведені вище, точно еквівалентні.

<Component { ...props } />

1
Поки пов’язані, не змішуйте синтаксис розповсюдження JSX із властивостями відпочинку .
Фелікс Клінг,

3
"Це дозволяє" розподілити "всі свої реквізити в одному стислому виразі." Це не правильно. ...restв { component: Component, ...rest } збирає всі інші властивості об'єкта rest. Питання про ...rest, а не{...props}
Фелікс Клінг

Як зазначає Фелікс, слід розрізняти (нестандартний) оператор розповсюдження об'єктів у JSX та оператор розповсюдження решта _ / _, як визначено у специфікації ECMAScript 2015. З одного боку, намагаючись написати що - щось на зразок { ...myObj }в не-React середовища ( наприклад , браузер консолі) буде кидати SyntaxError. Тим не менше, розповсюдження _6 _ ES6 забезпечує корисну концептуальну основу для роздумів про розповсюдження об'єктів JSX .
IsenrichO

4

Давайте спростимо: у JavaScript, якщо пари "ключ: значення" однакові, obj={account:account}це те саме, що obj={account}. Отже, при передачі реквізиту від батьківського до дочірнього компонента:

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;

ви будете здавати решту реквізиту як:

label={label} placeholder={placeholder} type={type}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.