React 구성 요소가 다시 렌더링되는 이유 추적
React에서 컴포넌트가 다시 렌더링되는 원인을 디버깅하는 체계적인 접근 방식이 있습니까? 간단한 console.log ()를 넣어 렌더링 시간을 확인했지만 구성 요소가 여러 번 렌더링되는 원인을 파악하는 데 문제가 있습니다. 타임 라인 및 / 또는 모든 구성 요소 트리 렌더링 및 순서를 보여주는 도구가 있습니까?
외부 의존성이없는 짧은 스 니펫을 원한다면 유용하다고 생각합니다.
componentDidUpdate(prevProps, prevState) {
Object.entries(this.props).forEach(([key, val]) =>
prevProps[key] !== val && console.log(`Prop '${key}' changed`)
);
if (this.state) {
Object.entries(this.state).forEach(([key, val]) =>
prevState[key] !== val && console.log(`State '${key}' changed`)
);
}
}
다음은 함수 구성 요소에 대한 업데이트를 추적하는 데 사용하는 작은 후크입니다.
function useTraceUpdate(props) {
const prev = useRef(props);
useEffect(() => {
const changedProps = Object.entries(props).reduce((ps, [k, v]) => {
if (prev.current[k] !== v) {
ps[k] = [prev.current[k], v];
}
return ps;
}, {});
if (Object.keys(changedProps).length > 0) {
console.log('Changed props:', changedProps);
}
prev.current = props;
});
}
// Usage
function MyComponent(props) {
useTraceUpdate(props);
return <div>{props.children}</div>;
}
다음은 React 컴포넌트가 다시 렌더링되는 몇 가지 인스턴스입니다.
- 상위 구성 요소 다시 렌더링
this.setState()
구성 요소 내에서 호출 합니다. 이것은 다음과 같은 구성 요소 수명주기 방법 트리거shouldComponentUpdate
>componentWillUpdate
>render
>을componentDidUpdate
- 구성 요소의
props
. 이 의지 트리거componentWillReceiveProps
>shouldComponentUpdate
>componentWillUpdate
>render
>componentDidUpdate
(connect
방법react-redux
트리거 이것을 돌아 오는 저장소에 해당하는 변경 사항이있을 경우) this.forceUpdate
비슷한 전화this.setState
내부 검사를 구현하고 필요하지 않은 경우 shouldComponentUpdate
반환 하여 구성 요소의 다시 렌더링을 최소화 할 수 있습니다 false
.
또 다른 방법은 또는 상태 비 저장 구성 요소 를 사용하는 것입니다 React.PureComponent
. 순수 및 상태 비 저장 구성 요소는 소품에 변경 사항이있을 때만 다시 렌더링됩니다.
@jpdelatorre의 답변은 React 구성 요소가 다시 렌더링되는 일반적인 이유를 강조하는 데 좋습니다.
I just wanted to dive a little deeper into one instance: when props change. Troubleshooting what is causing a React component to re-render is a common issue, and in my experience a lot of the times tracking down this issue involves determining which props are changing.
React components re-render whenever they receive new props. They can receive new props like:
<MyComponent prop1={currentPosition} prop2={myVariable} />
or if MyComponent
is connected to a redux store:
function mapStateToProps (state) {
return {
prop3: state.data.get('savedName'),
prop4: state.data.get('userCount')
}
}
Anytime the value of prop1
, prop2
, prop3
, or prop4
changes MyComponent
will re-render. With 4 props it is not too difficult to track down which props are changing by putting a console.log(this.props)
at that beginning of the render
block. However with more complicated components and more and more props this method is untenable.
Here is a useful approach (using lodash for convenience) to determine which prop changes are causing a component to re-render:
componentWillReceiveProps (nextProps) {
const changedProps = _.reduce(this.props, function (result, value, key) {
return _.isEqual(value, nextProps[key])
? result
: result.concat(key)
}, [])
console.log('changedProps: ', changedProps)
}
Adding this snippet to your component can help reveal the culprit causing questionable re-renders, and many times this helps shed light on unnecessary data being piped into components.
There's now a hook for this available on npm:
https://www.npmjs.com/package/use-trace-update
(Disclosure, I published it)
The above answers are very helpful, just in case if anyone is looking for a specfic method to detect the cause of rerender then I found this library redux-logger very helpful.
What you can do is add the library and enable diffing between state(it is there in the docs) like:
const logger = createLogger({
diff: true,
});
And add the middleware in the store.
Then put a console.log()
in the render function of the component you want to test.
Then you can run your app and check for console logs.Wherever there is a log just before it will show you difference between state (nextProps and this.props)
and you can decide if render is really needed there
It will similar to above image along with the diff key.
Strange nobody has given that answer but I find it very useful, especially since the props changes are almost always deeply nested.
Hooks fanboys:
import deep_diff from "deep-diff";
const withPropsChecker = WrappedComponent => {
return props => {
const prevProps = useRef(props);
useEffect(() => {
const diff = deep_diff.diff(prevProps.current, props);
if (diff) {
console.log(diff);
}
prevProps.current = props;
});
return <WrappedComponent {...props} />;
};
};
"Old"-school fanboys:
import deep_diff from "deep-diff";
componentDidUpdate(prevProps, prevState) {
const diff = deep_diff.diff(prevProps, this.props);
if (diff) {
console.log(diff);
}
}
P.S. I still prefer to use HOC(higher order component) because sometimes you have destructured your props at the top and Jacob's solution doesn't fit well
Disclaimer: No affiliation whatsoever with the package owner. Just clicking tens of times around to try to spot the difference in deeply nested objects is a pain in the.
참고URL : https://stackoverflow.com/questions/41004631/trace-why-a-react-component-is-re-rendering
'program tip' 카테고리의 다른 글
두 필드 비교시 MongoDb 쿼리 조건 (0) | 2020.08.30 |
---|---|
React.js의 setState 대 replaceState (0) | 2020.08.30 |
Ruby에서 문자열 대신 기호를 사용하는 경우 (0) | 2020.08.30 |
$ http get 매개 변수가 작동하지 않습니다. (0) | 2020.08.30 |
Python : 튜플 / 사전을 키, 선택, 정렬 (0) | 2020.08.30 |