Что это значит… отдыхайте в React JSX


83

Глядя на этот пример 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, получите свойство Component, а затем все остальные предоставленные вам реквизиты и переименуйте его propsв, restчтобы избежать проблем с именованием свойств, переданных в renderфункцию Route.

Я прав?


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( Примечание : в нижнем регистре с 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с большой буквы «C»?

Да, это кажется довольно тривиальным. И хотя это стандартная практика React, есть причина, по которой вся документация Facebook по его фреймворку написана именно так. А именно, использование заглавных букв в пользовательских компонентах, отображаемых с помощью JSX, - это не столько практика как таковая, сколько необходимость. React, точнее, 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
«Это позволяет вам« раскрыть »все ваши реквизиты в одном кратком выражении». Это не правильно. ...restin { component: Component, ...rest } собирает все остальные свойства объекта rest. Вопрос в том ...rest, а не в{...props}
Феликс Клинг

Как отмечает Феликс, существует различие между (нестандартным) оператором распространения объекта в JSX и остальным оператором распространения _ / _, как определено в спецификации ECMAScript 2015. Во-первых, попытка написать что-то вроде { ...myObj }в среде, отличной от React ( например , в консоли браузера), вызовет ошибку SyntaxError. Тем не менее, остальные _ / _ распространения ES6 предоставляют полезную концептуальную основу для размышлений о распространении объектов JSX .
IsenrichO

4

Давайте будем простыми: в JavaScript, если пары «ключ: значение» совпадают, obj={account:account}то же самое, что и obj={account}. Итак, при передаче props от родительского к дочернему компоненту:

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.