이것이 의미하는 바는… 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 }의미 하는 것을 확신하고 싶다 .

에서 propsComponent prop와 다른 모든 props를받은 후 이름 props을로 변경 rest하여 Route render함수에 전달 된 props의 이름 지정 문제를 방지 할 수 있습니다.

내가 맞아?


5

답변:


156

죄송합니다. 첫 번째 답변 (유용한 / 추가적인 컨텍스트를 제공하는 동안)이 귀하의 질문에 답변하지 않는다는 것을 깨달았습니다. 다시 해보겠습니다.

물어:

나는 확신하고 싶다 { component: Component, ...rest } 의미는 다음과 같습니다.

에서 props의 얻을 Component다른 모든 다음 소품을하고 props당신에게 주어지고, 이름 바꾸기 propsrest당신이 문제를 명명 피할 수 있도록 props라우트로 전달 render기능

귀하의 해석이 정확하지 않습니다. 하지만 당신의 생각에 따르면, 여기에서 일어나는 일이 일종의 객체 파괴 에 해당한다는 사실을 적어도 알고있는 것 같습니다. (더 자세한 설명은 두 번째 답변 및 주석 참조).

정확한 설명을 제공하기 위해 { component: Component, ...rest }표현식을 두 개의 개별 작업으로 나눕니다.

  1. 작업 1 :component 정의 된 속성 찾기 props( 참고 : 소문자 C creationComplete 컴퍼넌트) 우리가 부르는 상태에서 새 위치를 지정 Component( 참고 : 자본 C creationComplete 컴퍼넌트).
  2. 작업 2 : 그런 다음 개체에 정의 된 나머지 속성 을 모두 props가져와라는 인수 내에서 수집합니다 rest.

중요한 점은 이름을 바꾸지 않는다는 것입니다. propsrest. (또한 " propsRoute render함수에 전달 된 이름 지정 문제를 피하려는 시도와도 관련이 없습니다 .)

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, sexdob)을 가져 와서 이름을 지정한 변수에 할당 된 새 개체로 수집합니다 rest.

로깅 Usernamerest에이를 console확인합니다. 우리는 다음을 가지고 있습니다 :

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

사이드 노트

다음과 같은 질문이있을 수 있습니다.

대문자 "C" component로 이름을 변경하기 위해 재산 을 떼어내는 수고를 겪는 이유는 무엇 Component입니까?

예, 꽤 사소한 것 같습니다. 그리고 이것이 표준 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'
}

이러한 항목 ( 예 : , thing1thing2)을 중첩 된 <Component />태그 로 더 전달하고 싶고 객체 확산 구문에 익숙하지 않은 경우 다음과 같이 작성할 수 있습니다.

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

그러나 { ...props }구문 은 값 배열 ( 예 : , )을 분산 하는 것과 같은 방식으로 객체 를 분산 할 수 있도록함으로써 이러한 자세한 정보를 제거 합니다 . 즉, 아래의 JSX 표현식과 위의 표현식은 정확히 동일합니다.props[...vals]

<Component { ...props } />

1
관련이 있지만 JSX의 스프레드 구문을 나머지 속성 과 혼합하지 마십시오 .
Felix Kling

3
"간결한 단일 표현으로 모든 소품을"확산 "할 수 있습니다." 그건 아니지. ...restin { component: Component, ...rest } 객체의 다른 모든 속성 을 수집 합니다 rest. 질문에 관한 ...rest하지{...props}
펠릭스 클링

Felix가 지적 했듯이 JSX 의 (비표준) 객체 확산 연산자와 ECMAScript 2015 사양에 정의 된 rest _ / _ spread 연산자 사이에는 구별이 있습니다 . 우선, { ...myObj }비 React 환경 ( 예 : 브라우저 콘솔) 에서 같은 것을 작성하려고 하면 SyntaxError. 그럼에도 불구하고 ES6의 rest _ / _ spread 는 JSX의 객체 확산 을 생각할 수있는 유용한 개념적 프레임 워크를 제공합니다 .
IsenrichO

4

간단하게 유지하자. 자바 스크립트에서 "키 : 값" 쌍이 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}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.