[javascript] JSX 소품이 화살표 함수 나 바인드를 사용하지 않는 이유는 무엇입니까?

React 앱에서 Lint를 실행하고 있는데이 오류가 발생합니다.

error    JSX props should not use arrow functions        react/jsx-no-bind

그리고 이것은 내가 화살표 기능을 실행하는 곳입니다 (내부 onClick).

{this.state.photos.map(tile => (
  <span key={tile.img}>
    <Checkbox
      defaultChecked={tile.checked}
      onCheck={() => this.selectPicture(tile)}
      style={{position: 'absolute', zIndex: 99, padding: 5, backgroundColor: 'rgba(255, 255, 255, 0.72)'}}
    />
    <GridTile
      title={tile.title}
      subtitle={<span>by <b>{tile.author}</b></span>}
      actionIcon={<IconButton onClick={() => this.handleDelete(tile)}><Delete color="white"/></IconButton>}
    >
      <img onClick={() => this.handleOpen(tile.img)} src={tile.img} style={{cursor: 'pointer'}}/>
    </GridTile>
  </span>
))}

피해야 할 나쁜 습관입니까? 그리고 그것을 수행하는 가장 좋은 방법은 무엇입니까?



답변

JSX 소품에서 인라인 화살표 함수를 사용하지 말아야하는 이유

JSX에서 화살표 함수 또는 바인딩을 사용하는 것은 함수가 각 렌더링에서 다시 생성되기 때문에 성능을 저하시키는 나쁜 습관입니다.

  1. 함수가 생성 될 때마다 이전 함수는 가비지 수집됩니다. 많은 요소를 렌더링하면 애니메이션에서 버벅 거림이 발생할 수 있습니다.

  2. 인라인 화살표 함수를 사용하면 PureComponents 및 메서드 shallowCompare에서 사용하는 구성 요소가 shouldComponentUpdate어쨌든 다시 렌더링됩니다. 화살표 함수 소품은 매번 다시 생성되기 때문에 얕은 비교는 소품의 변경 사항으로 식별하고 구성 요소가 다시 렌더링됩니다.

다음 두 가지 예에서 볼 수 있듯이 인라인 화살표 기능을 사용하면 <Button>구성 요소가 매번 다시 렌더링됩니다 (콘솔에 ‘렌더링 버튼’텍스트가 표시됨).

예제 1- 인라인 핸들러가 없는 PureComponent

예 2 – PureComponent 인라인 핸들러

this인라인 화살표 함수없이 메서드 바인딩

  1. 생성자에서 수동으로 메서드 바인딩 :

    class Button extends React.Component {
      constructor(props, context) {
        super(props, context);
    
        this.cb = this.cb.bind(this);
      }
    
      cb() {
    
      }
    
      render() {
        return (
          <button onClick={ this.cb }>Click</button>
        );
      }
    }
  2. 제안 클래스 필드 를 화살표 함수와 함께 사용하여 메서드를 바인딩 합니다. 이것은 3 단계 제안이므로 3 단계 사전 설정 또는 클래스 속성 변환 을 바벨 구성 에 추가해야 합니다.

    class Button extends React.Component {
      cb = () => { // the class property is initialized with an arrow function that binds this to the class
    
      }
    
      render() {
        return (
          <button onClick={ this.cb }>Click</button>
        );
      }
    }

내부 콜백이있는 함수 구성 요소

함수 구성 요소 내에 내부 함수 (예 : 이벤트 처리기)를 만들면 구성 요소가 렌더링 될 때마다 함수가 다시 만들어집니다. 함수가 소품으로 (또는 컨텍스트를 통해) 자식 구성 요소 ( Button이 경우)에 전달되면 해당 자식도 다시 렌더링됩니다.

예제 1-내부 콜백이있는 함수 구성 요소 :

이 문제를 해결하기 위해 콜백을 useCallback()hook으로 래핑 하고 종속성을 빈 배열로 설정할 수 있습니다.

참고useState 생성 기능의 현재 상태를 제공하는 업데이터 기능을 수용한다. 이런 식으로 현재 상태를의 종속성으로 설정할 필요가 없습니다 useCallback.

예제 2-useCallback으로 래핑 된 내부 콜백이있는 함수 구성 요소 :


답변

이는 화살표 함수가 JSX 속성에서 사용되는 경우 각 렌더링에서 함수의 새 인스턴스를 분명히 생성하기 때문입니다. 이것은 가비지 컬렉터에 큰 부담을 줄 수 있으며 또한 함수가 재사용되는 대신 버려 질 것이기 때문에 브라우저가 “핫 경로”를 최적화하는 것을 방해합니다.

https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md 에서 전체 설명과 추가 정보를 볼 수 있습니다.


답변

동일한 인수로 새 함수를 생성하지 않으려면 함수 바인드 결과를 메모 할 수 있습니다. 다음은이 memobind를 수행 하는 간단한 유틸리티입니다 . https://github.com/supnate/memobind


답변

이와 같은 인라인 함수를 사용하는 것은 완벽합니다. Linting 규칙이 오래되었습니다.

이 규칙은 화살표 기능이 흔하지 않았고 사람들이 .bind (this)를 사용했던 때부터 시작되었습니다. Chrome 49에서 성능 문제가 수정되었습니다.

인라인 함수를 자식 구성 요소에 소품으로 전달하지 않도록주의하십시오.

React Router의 저자 인 Ryan Florence는 이에 대해 훌륭한 글을 썼습니다.

https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578


답변

react-cached-handler 라이브러리를 사용하여 화살표 함수를 사용할 수 있으며 다시 렌더링 성능에 대해 걱정할 필요가 없습니다.

참고 : 내부적으로는 지정된 키로 화살표 기능을 캐시하므로 다시 렌더링 할 필요가 없습니다!

render() {

  return <div>
  {
        this.props.photos.map(photo=>
          <Photo key={photo.url}
            onClick={this.handler(photo.url, (url) => {
                 console.log(url) })}
          />)
   }
 </div>

}

다른 기능들:

  • 명명 된 핸들러
  • 화살표 기능으로 이벤트 처리
  • 키, 사용자 지정 인수 및 원래 이벤트에 대한 액세스
  • 컴포넌트 렌더링 성능
  • 핸들러를위한 커스텀 컨텍스트

답변

JSX 소품이 화살표 함수 나 바인드를 사용하지 않는 이유는 무엇입니까?

대부분 인라인 함수는 최적화 된 구성 요소의 메모 화를 중단 할 수 있기 때문입니다.

전통적으로 React의 인라인 함수에 대한 성능 문제는 각 렌더링에서 새 콜백을 전달하면 shouldComponentUpdate자식 구성 요소의 최적화 가 어떻게 중단되는지와 관련이 있습니다. ( 문서 )

추가 기능 생성 비용이 적습니다.

Function.prototype.bind 여기서 해결 성능 문제와 화살표 함수는 기본 기능이거나 바벨에 의해 일반 함수로 변환됩니다. 두 경우 모두 느리지 않다고 가정 할 수 있습니다. ( 반응 훈련 )

나는 함수 생성이 비싸다고 주장하는 사람들이 항상 잘못된 정보를 받았다고 생각합니다 (React 팀은 이것을 결코 말하지 않았습니다). ( 트윗 )

react/jsx-no-bind규칙 은 언제 유용합니까?

메모 된 구성 요소가 의도 한대로 작동하는지 확인하려고합니다.

  • React.memo (기능 구성 요소)
  • PureComponent또는 사용자 정의 shouldComponentUpdate(클래스 구성 요소 용)

이 규칙에 따라 안정적인 함수 개체 참조가 전달됩니다. 따라서 위의 구성 요소는 이전 소품이 변경되지 않은 경우 다시 렌더링을 방지하여 성능을 최적화 할 수 있습니다.

ESLint 오류를 해결하는 방법은 무엇입니까?

클래스 : 핸들러를 메서드로 정의하거나 바인딩을 위한 클래스 속성 을 정의합니다 this.
후크 : useCallback.

중앙 필드

대부분의 경우 인라인 함수는 사용하기 매우 편리하고 성능 요구 사항 측면에서 절대적으로 좋습니다. 안타깝게도이 규칙은 메모 된 구성 요소 유형으로 만 제한 될 수 없습니다. 그래도 전체적으로 사용하려면 간단한 DOM 노드에 대해 비활성화 할 수 있습니다 .

rules: {
  "react/jsx-no-bind": [ "error", { ignoreDOMComponents: true } ],
}

const Comp = () => <span onClick={() => console.log("Hello!")} />; // no warning


답변