요소의 높이 ( “app-content”라고 함)를 동적으로 설정해야하는 앱이 있습니다. 앱의 “크롬”높이를 빼고 빼서 “응용 프로그램 콘텐츠”높이를 해당 제한 내에서 100 %에 맞게 설정합니다. 바닐라 JS, jQuery 또는 Backbone 뷰에서는 매우 간단하지만 React에서 올바른 프로세스가 무엇인지 알아 내려고 고심하고 있습니다.
아래는 예제 구성 요소입니다. app-content
높이를 창의 100 %에서 ActionBar
and 의 크기를 뺀 값 으로 설정할 수 있기를 원 BalanceBar
하지만 모든 것이 렌더링되는 시점 과이 React 클래스에서 계산 항목을 어디에 넣을지 어떻게 알 수 있습니까?
/** @jsx React.DOM */
var List = require('../list');
var ActionBar = require('../action-bar');
var BalanceBar = require('../balance-bar');
var Sidebar = require('../sidebar');
var AppBase = React.createClass({
render: function () {
return (
<div className="wrapper">
<Sidebar />
<div className="inner-wrapper">
<ActionBar title="Title Here" />
<BalanceBar balance={balance} />
<div className="app-content">
<List items={items} />
</div>
</div>
</div>
);
}
});
module.exports = AppBase;
답변
이 메소드는 컴포넌트가 렌더링 된 후에 한 번 호출됩니다. 따라서 코드는 다음과 같습니다.
var AppBase = React.createClass({
componentDidMount: function() {
var $this = $(ReactDOM.findDOMNode(this));
// set el height and width etc.
},
render: function () {
return (
<div className="wrapper">
<Sidebar />
<div className="inner-wrapper">
<ActionBar title="Title Here" />
<BalanceBar balance={balance} />
<div className="app-content">
<List items={items} />
</div>
</div>
</div>
);
}
});
답변
한 사용의 단점 componentDidUpdate
, 또는 componentDidMount
DOM을 요소가 그려지 완료하기 전에이 실제로 실행하는 것입니다,하지만 그들은에서 통과 한 후에 브라우저의 DOM에 반응한다.
예를 들어 node.scrollHeight를 렌더링 된 node.scrollTop으로 설정해야한다면 React의 DOM 요소로는 충분하지 않을 수 있습니다. 높이를 얻기 위해 요소가 칠해질 때까지 기다려야합니다.
해결책:
requestAnimationFrame
새로 렌더링 된 객체를 페인팅 한 후 코드가 실행되도록하는 데 사용
scrollElement: function() {
// Store a 'this' ref, and
var _this = this;
// wait for a paint before running scrollHeight dependent code.
window.requestAnimationFrame(function() {
var node = _this.getDOMNode();
if (node !== undefined) {
node.scrollTop = node.scrollHeight;
}
});
},
componentDidMount: function() {
this.scrollElement();
},
// and or
componentDidUpdate: function() {
this.scrollElement();
},
// and or
render: function() {
this.scrollElement()
return [...]
답변
내 경험상 window.requestAnimationFrame
DOM이에서 완전히 리플 로우 / 리플 로우 완료되었는지 확인하기에 충분하지 않았습니다 componentDidMount
. componentDidMount
호출 직후 DOM에 액세스하는 코드를 실행 중이며 단독으로 사용 window.requestAnimationFrame
하면 DOM에 요소가 존재합니다. 그러나 리플 로우가 아직 발생하지 않았으므로 요소의 치수에 대한 업데이트는 아직 반영되지 않습니다.
이 작업을 수행 할 수있는 진정으로 신뢰할 수있는 유일한 방법 은 다음 프레임의 렌더에 등록하기 전에 React의 현재 호출 스택이 지워지도록 메소드를 a setTimeout
와 a 로 감싸는 것 window.requestAnimationFrame
입니다.
function onNextFrame(callback) {
setTimeout(function () {
requestAnimationFrame(callback)
})
}
이것이 왜 발생하고 필요한지 추측 해야하는 경우 React batching DOM 업데이트를보고 현재 스택이 완료 될 때까지 DOM에 변경 사항을 실제로 적용하지 않을 수 있습니다.
궁극적으로 React 콜백 후에 발생하는 코드에서 DOM 측정을 사용하는 경우이 방법을 사용하는 것이 좋습니다.
답변
새로운 Hook 메소드 로이 질문을 약간 업데이트하려면 useEffect
후크 를 사용하면됩니다 .
import React, { useEffect } from 'react'
export default function App(props) {
useEffect(() => {
// your post layout code (or 'effect') here.
...
},
// array of variables that can trigger an update if they change. Pass an
// an empty array if you just want to run it once after component mounted.
[])
}
또한 레이아웃 페인트 전에 실행하려면 useLayoutEffect
후크를 사용하십시오 .
import React, { useLayoutEffect } from 'react'
export default function App(props) {
useLayoutEffect(() => {
// your pre layout code (or 'effect') here.
...
}, [])
}
답변
상태를 변경 한 다음 setState 콜백 에서 계산을 수행 할 수 있습니다 . React 문서에 따르면, 이것은 “업데이트가 적용된 후에 발생하도록 보장됩니다”.
이것은 componentDidMount
생성자가 아닌 코드의 크기 조정 이벤트 핸들러와 같이 또는 다른 곳에서 수행해야합니다 .
이것은 좋은 대안 window.requestAnimationFrame
이며 여기에서 일부 사용자가 언급 한 문제가 없습니다 ( setTimeout
복합하거나 여러 번 호출해야 함). 예를 들면 다음과 같습니다.
class AppBase extends React.Component {
state = {
showInProcess: false,
size: null
};
componentDidMount() {
this.setState({ showInProcess: true }, () => {
this.setState({
showInProcess: false,
size: this.calculateSize()
});
});
}
render() {
const appStyle = this.state.showInProcess ? { visibility: 'hidden' } : null;
return (
<div className="wrapper">
...
<div className="app-content" style={appStyle}>
<List items={items} />
</div>
...
</div>
);
}
}
답변
나는이 솔루션이 더럽다고 생각하지만 여기에 우리는 간다.
componentDidMount() {
this.componentDidUpdate()
}
componentDidUpdate() {
// A whole lotta functions here, fired after every render.
}
이제 난 그냥 여기 앉아서 아래로 투표를 기다립니다.
답변
React에는 getInitialState, getDefaultProps, componentWillMount, componentDidMount 등 을 포함하지만 이에 국한되지 않는 이러한 상황에서 도움이되는 수명주기 메소드가 거의 없습니다 .
귀하의 경우와 DOM 요소와 상호 작용 해야하는 경우 dom이 준비 될 때까지 기다려야하므로 다음과 같이 componentDidMount 를 사용하십시오 .
/** @jsx React.DOM */
var List = require('../list');
var ActionBar = require('../action-bar');
var BalanceBar = require('../balance-bar');
var Sidebar = require('../sidebar');
var AppBase = React.createClass({
componentDidMount: function() {
ReactDOM.findDOMNode(this).height = /* whatever HEIGHT */;
},
render: function () {
return (
<div className="wrapper">
<Sidebar />
<div className="inner-wrapper">
<ActionBar title="Title Here" />
<BalanceBar balance={balance} />
<div className="app-content">
<List items={items} />
</div>
</div>
</div>
);
}
});
module.exports = AppBase;
또한 반응의 수명주기에 대한 자세한 내용은 다음 링크를 참조하십시오.
https://facebook.github.io/react/docs/state-and-lifecycle.html