[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에서 화살표 함수 또는 바인딩을 사용하는 것은 함수가 각 렌더링에서 다시 생성되기 때문에 성능을 저하시키는 나쁜 습관입니다.
-
함수가 생성 될 때마다 이전 함수는 가비지 수집됩니다. 많은 요소를 렌더링하면 애니메이션에서 버벅 거림이 발생할 수 있습니다.
-
인라인 화살표 함수를 사용하면
PureComponent
s 및 메서드shallowCompare
에서 사용하는 구성 요소가shouldComponentUpdate
어쨌든 다시 렌더링됩니다. 화살표 함수 소품은 매번 다시 생성되기 때문에 얕은 비교는 소품의 변경 사항으로 식별하고 구성 요소가 다시 렌더링됩니다.
다음 두 가지 예에서 볼 수 있듯이 인라인 화살표 기능을 사용하면 <Button>
구성 요소가 매번 다시 렌더링됩니다 (콘솔에 ‘렌더링 버튼’텍스트가 표시됨).
예제 1- 인라인 핸들러가 없는 PureComponent
예 2 – PureComponent 와 인라인 핸들러
this
인라인 화살표 함수없이 메서드 바인딩
-
생성자에서 수동으로 메서드 바인딩 :
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> ); } }
-
제안 클래스 필드 를 화살표 함수와 함께 사용하여 메서드를 바인딩 합니다. 이것은 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