componentDidMount가 참조 콜백 전에 호출 됨
문제
ref
인라인 함수 정의를 사용하여 반응 을 설정하고 있습니다.
render = () => {
return (
<div className="drawer" ref={drawer => this.drawerRef = drawer}>
그런 다음 componentDidMount
DOM 참조가 설정되지 않았습니다.
componentDidMount = () => {
// this.drawerRef is not defined
내 이해는 ref
콜백이 마운트 중에 실행되어야한다는 것입니다. 그러나 console.log
문을 추가 하면 ref 콜백 함수 componentDidMount
가 호출 되기 전에 호출됩니다.
내가 예를 들어 검토 한 다른 코드 샘플 이 토론 GitHub의에서이 같은 가정을 나타낸다는 componentDidMount
호출 할 필요가 이후 어떤 ref
정의 콜백 render
이도있어, 대화에 명시된
그래서 모든 ref 콜백이 실행 된 후에 componentDidMount가 시작됩니까?
예.
반응 15.4.1을 사용하고 있습니다.
내가 시도한 다른 것
ref
함수가 호출 되었는지 확인하기 위해 클래스에서 다음과 같이 정의 해 보았습니다.
setDrawerRef = (drawer) => {
this.drawerRef = drawer;
}
그런 다음 render
<div className="drawer" ref={this.setDrawerRef}>
이 경우 콘솔 로깅은 콜백이 실제로 호출되고 계시 후 componentDidMount
짧은 답변:
React는 ref가 componentDidMount
또는 componentDidUpdate
hooks 이전에 설정되도록 보장합니다 . 그러나 실제로 렌더링 된 어린이에게만 해당 됩니다 .
componentDidMount() {
// can use any refs here
}
componentDidUpdate() {
// can use any refs here
}
render() {
// as long as those refs were rendered!
return <div ref={/* ... */} />;
}
이것이 "React는 이러한 후크가 실행되기 전에 항상 모든 참조를 설정 합니다 "를 의미하지는 않습니다 .
참조 가 설정 되지 않은 몇 가지 예를 살펴 보겠습니다 .
렌더링되지 않은 요소에 대한 참조가 설정되지 않습니다.
React는 render에서 실제로 반환 한 요소에 대해서만 ref 콜백을 호출 합니다.
이것은 코드가
render() {
if (this.state.isLoading) {
return <h1>Loading</h1>;
}
return <div ref={this._setRef} />;
}
그리고 처음 this.state.isLoading
입니다 true
당신이해야 하지 기대 this._setRef
하기 전에 호출 할 componentDidMount
.
이것은 의미가있을 것입니다 : 만약 당신의 첫 번째 렌더링이 반환 되었다면 <h1>Loading</h1>
, React가 어떤 다른 조건 하에서 ref를 첨부해야하는 다른 것을 반환한다는 것을 알 수있는 방법이 없습니다. 또한이 없다 :에 심판 설정하는 것도<div>
때문에 요소가 작성되지 않았습니다 render()
방법은 렌더링되지 않을 것이라고 말했다는.
따라서이 예제에서는 만 componentDidMount
실행됩니다. 그러나 경우 this.state.loading
에 변경false
, 당신은 볼 것이다 this._setRef
첫째 부착 한 다음 componentDidUpdate
실행됩니다.
다른 구성 요소에주의
참고 것을 당신이 다른 구성 요소에 이르기까지 심판 어린이를 전달하는 경우 가 방지 렌더링 (그리고 문제로 인해) 뭔가를하고있는 기회가있다.
예를 들면 다음과 같습니다.
<MyPanel>
<div ref={this.setRef} />
</MyPanel>
출력에 MyPanel
포함하지 않으면 작동 하지 않습니다 props.children
.
function MyPanel(props) {
// ignore props.children
return <h1>Oops, no refs for you today!</h1>;
}
다시 말하지만, 그것은 버그가 아닙니다 : DOM 요소가 생성되지 않았기 때문에 React가 ref를 설정할 아무것도 없을 것입니다 .
참조가 중첩으로 전달되는 경우 수명주기 전에 설정되지 않습니다. ReactDOM.render()
이전 섹션과 마찬가지로 ref가있는 자식을 다른 구성 요소에 전달하면이 구성 요소가 시간 내에 ref를 첨부하지 못하게하는 작업을 수행 할 수 있습니다.
For example, maybe it’s not returning the child from render()
, and instead is calling ReactDOM.render()
in a lifecycle hook. You can find an example of this here. In that example, we render:
<MyModal>
<div ref={this.setRef} />
</MyModal>
But MyModal
performs a ReactDOM.render()
call in its componentDidUpdate
lifecycle method:
componentDidUpdate() {
ReactDOM.render(this.props.children, this.targetEl);
}
render() {
return null;
}
Since React 16, such top-level render calls during a lifecycle will be delayed until lifecycles have run for the whole tree. This would explain why you’re not seeing the refs attached in time.
The solution to this problem is to use portals instead of nested ReactDOM.render
calls:
render() {
return ReactDOM.createPortal(this.props.children, this.targetEl);
}
This way our <div>
with a ref is actually included in the render output.
So if you encounter this issue, you need to verify there’s nothing between your component and the ref that might delay rendering children.
Don't use setState
to store refs
Make sure you are not using setState
to store the ref in ref callback, as it's asynchronous and before it's "finished", componentDidMount
will be executed first.
Still an Issue?
If none of the tips above help, file an issue in React and we will take a look.
A different observation of the problem.
I've realised that the issue only occurred while in development mode. After more investigation, I found that disabling react-hot-loader
in my Webpack config prevents this problem.
I am using
- "react-hot-loader": "3.1.3"
- "webpack": "4.10.2",
And it's an electron app.
My partial Webpack development config
const webpack = require('webpack')
const merge = require('webpack-merge')
const baseConfig = require('./webpack.config.base')
module.exports = merge(baseConfig, {
entry: [
// REMOVED THIS -> 'react-hot-loader/patch',
`webpack-hot-middleware/client?path=http://localhost:${port}/__webpack_hmr`,
'@babel/polyfill',
'./app/index'
],
...
})
It became suspicious when I saw that using inline function in render () was working, but using a bound method was crashing.
Works in any case
class MyComponent {
render () {
return (
<input ref={(el) => {this.inputField = el}}/>
)
}
}
Crash with react-hot-loader (ref is undefined in componentDidMount)
class MyComponent {
constructor (props) {
super(props)
this.inputRef = this.inputRef.bind(this)
}
inputRef (input) {
this.inputField = input
}
render () {
return (
<input ref={this.inputRef}/>
)
}
}
To be honest, hot reload has often been problematic to get "right". With dev tools updating fast, every project has a different config. Maybe my particular config could be fixed. I'll let you know here if that's the case.
In componentDidMount, can you find your ref element (div.drawer) in the browser DOM? If not, you can't have its reference. Since the problem is found in another, larger code, the reason could be that ref element (div.drawer) is not rendered.
참고URL : https://stackoverflow.com/questions/44074747/componentdidmount-called-before-ref-callback
'code' 카테고리의 다른 글
알파벳 순서 대신 ggplot2 x 축을 구체적으로 어떻게 주문합니까? (0) | 2020.11.11 |
---|---|
갈래 저장소에서 git master 브랜치를 업스트림 브랜치로 재설정하려면 어떻게해야합니까? (0) | 2020.11.11 |
Oracle의 OVER 절 (0) | 2020.11.11 |
log4j가 예외에 대한 스택 추적을 인쇄하지 않습니다. (0) | 2020.11.11 |
파이썬을 사용하여 실제 사용자 홈 디렉토리를 찾는 방법은 무엇입니까? (0) | 2020.11.11 |